Cache Aside Pattern 即旁路缓存是缓存方案的经验实践,这个实践又分读实践,写实践

对于读请求

  • 先读cache,再读db

  • 如果,cache hit,则直接返回数据

  • 如果,cache miss,则访问db,并将数据set回缓存

如上图:

(1)先从cache中尝试get数据,结果miss了

(2)再从db中读取数据,从库,读写分离

(3)最后把数据set回cache,方便下次读命中

对于写请求

  • 淘汰缓存,而不是更新缓存

  • 先操作数据库,再淘汰缓存

如上图:

 (1)第一步要操作数据库,第二步操作缓存

(2)缓存,采用delete淘汰,而不是set更新

Cache Aside Pattern为什么建议淘汰缓存,而不是更新缓存?如果更新缓存,在并发写时,可能出现数据不一致。

如上图所示,如果采用set缓存。

在1和2两个并发写发生时,由于无法保证时序,此时不管先操作缓存还是先操作数据库,都可能出现:

(1)请求1先操作数据库,请求2后操作数据库

(2)请求2先set了缓存,请求1后set了缓存

导致,数据库与缓存之间的数据不一致。

所以,Cache Aside Pattern建议,delete缓存,而不是set缓存

Cache Aside Pattern为什么建议先操作数据库,再操作缓存?

如果先操作缓存,在读写并发时,可能出现数据不一致。

如上图所示,如果先操作缓存。

在1和2并发读写发生时,由于无法保证时序,可能出现:

(1)1.1 写请求淘汰了缓存

(2)1.2 写请求操作了数据库(主从同步没有完成)

(3)2.1 读请求读了缓存(cache miss)

(4)2.2 读请求读了从库(读了一个旧数据)

(5)2.3 读请求set回缓存(set了一个旧数据)

(6)1.3 数据库主从同步完成

导致,数据库与缓存的数据不一致。

所以,Cache Aside Pattern建议,先操作数据库,再操作缓存

先操作数据库再操作缓存, 在读写并发时,也可能出现数据不一致。

如上图所示,如果先操作数据库。

(1)1.1 读请求读了缓存(cache miss)

(2)1.2 读请求读了从库(读了一个旧数据)

(3)2.1 写请求操作了数据库

(4)2.2 写请求淘汰缓存(cache miss 淘汰跟没淘汰一样)

(5)1.3 读请求set回缓存(set了一个旧数据)

(6)2.3 数据库主从同步完成

导致,数据库与缓存的数据不一致

但是:先淘汰缓存再更新数据库方案中,写请求 淘汰缓存后 被 读请求 set回一个旧数据,这种并发出现的几率很大。 而: 先更新数据库再淘汰缓存方案中,读请求 在写请求之前读了数据且data miss,又要在写请求之后set缓存, 这种几率很小。 所以:Cache Aside Pattern建议,先操作数据库,再操作缓存。

Cache Aside Pattern方案存在什么问题?

:如果先操作数据库,再淘汰缓存,在原子性被破坏时:

(1)修改数据库成功了

(2)淘汰缓存失败了

导致,数据库与缓存的数据不一致。

参考:58沈剑 架构师之路

 

Cache Aside Pattern的更多相关文章

  1. 缓存实践Cache Aside Pattern

    Cache Aside Pattern旁路缓存,是对缓存应用的一个总结,包括读数据方案和写数据方案. 读数据方案 先读cache,如果命中则返回 如果miss则读db 将db的数据存入缓存 写数据方案 ...

  2. 别再犯低级错误,带你了解更新缓存的四种Desigh Pattern

    在我们使用分布式缓存Redis或者Memcached编写更新缓存数据代码时,我们总是会犯一个逻辑错误.先删除缓存,然后再更新数据库,而后续的操作会把数据再装载的缓存中.试想,两个并发操作,一个是更新操 ...

  3. cache and database

    This article referenced from http://coolshell.cn/articles/17416.html We all know that high concurren ...

  4. [Java复习] 缓存Cache part2

    7. Redis持久化有哪几种方式?不同的持久化机制都有什么优缺点?持久化机制具体底层是如何实现的? 为什么要持久化? 如果只是存在内存里,如果redis宕机再重启,内存数据就丢失了,所以要用持久化机 ...

  5. 缓存模式(Cache Aside、Read Through、Write Through、Write Behind)

    目录 概览 Cache-Aside 读操作 更新操作 缓存失效 缓存更新 Read-Through Write-Through Write-Behind 总结 参考 概览 缓存是一个有着更快的查询速度 ...

  6. Tomcat源码分析——SERVER.XML文件的加载与解析

    前言 作为Java程序员,对于Tomcat的server.xml想必都不陌生.本文基于Tomcat7.0的Java源码,对server.xml文件是如何加载和解析的进行分析. 加载 server.xm ...

  7. Memcache(1)

    一.缓存套路 原文地址:http://coolshell.cn/articles/17416.html Scaling Memcached at Facebook 好些人在写更新缓存数据代码时,先删除 ...

  8. 面试前必须要知道的Redis面试题

    前言 只有光头才能变强. 文本已收录至我的GitHub仓库,欢迎Star:https://github.com/ZhongFuCheng3y/3y 回顾前面: 从零单排学Redis[青铜] 从零单排学 ...

  9. redis缓存雪崩、缓存穿透、数据库和redis数据一致性

    一.缓存雪崩 回顾一下我们为什么要用缓存(Redis):减轻数据库压力或尽可能少的访问数据库. 在前面学习我们都知道Redis不可能把所有的数据都缓存起来(内存昂贵且有限),所以Redis需要对数据设 ...

随机推荐

  1. SpringBoot Mybatis项目中的多数据源支持

    1.概述 有时项目里里需要抽取不同系统中的数据源,需要访问不同的数据库,本文介绍在Springboot+Mybatis项目中如何支持多数据源操作. 有需要的同学可以下载 示例代码 项目结构如下: 2. ...

  2. Python_queue单项队列

    队列(queue),实现程序间的松耦合 队列的三种类: class queue.Queue(maxsize)# 先进先出, maxsize 指定队列长度,线程安全的清况下,可以放入实例,对实例进行传输 ...

  3. 昨天开始使用lr controller 已停止工作问题

    其实看到这个,只能看日志 看到日志也是无能为力 然后只能尝试修复,但是无法解决,最后通过重装系统,问题解决

  4. 深入理解Java虚拟机阅读心得(二)

    垃圾收集 程序计数器.虚拟机栈.本地方法栈三个区域随线程而生,随线程而灭:这几个区域的内存分配和回收都具备稳定性,不需要过多的考虑回收的问题.而Java堆和方法区则不一样. Java堆中存储了几乎所有 ...

  5. WPF: 共享Grid宽度或高度的方法

    需要两个属性: 1. Grid.IsSharedSizeScope="True" 2. SharedSizeGroup=名称 <StackPanel Margin=" ...

  6. ARC 103

    目录 官方题解 C 官方题解 C 这道题教会了我怎样正确统计众数和第二众数........... 我之前的方法是错的 #include <bits/stdc++.h> using name ...

  7. MVC:添加Html辅助器

    本文的方法来自 <精通asp.net Mvc5>. 一.添加视图模型 为了支持Html辅助器方法,可以把可用页面数,当前面,以及存储库中产品数等信息传递给视图.在Model文件夹内增加一个 ...

  8. NOIP-机器翻译

    题目描述 小晨的电脑上安装了一个机器翻译软件,他经常用这个软件来翻译英语文章. 这个翻译软件的原理很简单,它只是从头到尾,依次将每个英文单词用对应的中文含义来替换.对于每个英文单词,软件会先在内存中查 ...

  9. Vue(二十六)父子组件通信

    今天写了一个分页公共组件,就出现了父子组件通信的问题,今天来总结下我遇到的父子组件通信问题 一.子组件调取父组件的数据或方法 (1)props 想要把父组件的值,传到子组件中,使用props 比如你在 ...

  10. CSS3_线性渐变_径向渐变----背景

    渐变的本质: 绘制一张背景图片,所以使用 background 或者 background-image background 的诸多属性,渐变都是可以使用的(repeat,position) 百分比: ...