Cache Aside Pattern

简介: 在《究竟先操作缓存,还是数据库?》,有同学在评论提出,相关方案违背了“Cache Aside Pattern”的原则,故今天聊一聊Cache Aside Pattern。

在《究竟先操作缓存,还是数据库?》,有同学在评论提出,相关方案违背了“Cache Aside Pattern”的原则,故今天聊一聊Cache Aside Pattern。

另外,在讨论技术方案时,尽量不说:

“你是错的,应该怎么样”

“facebook不是这样,所以你是错的”

画外音:凭什么facebook就是真理?它的方案只是适合它的业务而已。

说明适用场景,说明来龙去脉,说明前因后果,比具体使用什么方案更重要。

什么是“Cache Aside Pattern”?

答:旁路缓存方案的经验实践,这个实践又分读实践,写实践。

对于读请求

先读cache,再读db

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

image.png

如上图:

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

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

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

画外音:这一点上,与《究竟先操作缓存,还是数据库?》说的是一致的。

对于写请求

  • 淘汰缓存,而不是更新缓存
  • 先操作数据库,再淘汰缓存

image.png

如上图:

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

画外音:这一点上,与《究竟先操作缓存,还是数据库?》说的不一致,也是评论反驳比较激烈的地方。

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

画外音:这一点上,与《缓存,究竟是淘汰,还是修改?》说的是一致的。

Cache Aside Pattern为什么建议淘汰缓存,而不是更新缓存?

答:如果更新缓存,在并发写时,可能出现数据不一致。

image.png

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

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

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

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

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

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

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

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

image.png

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

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

(1)写请求淘汰了缓存

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

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

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

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

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

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

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

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

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

(1)修改数据库成功了

(2)淘汰缓存失败了

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

如何解决这类问题呢?

答:详见《究竟先操作缓存,还是数据库?》。

任何技术方案的设计,都是折衷。

只有适合的方案,未必有最优的方案。

技术人,不是被动接受,而要主动思考。

image.png

目录
相关文章
|
Java Apache 容器
Invalid <url-pattern> /admin/*.jsp in filter mapping
完成错误信息 严重: A child container failed during start java.util.concurrent.ExecutionException: org.apache.
1175 0
|
缓存 关系型数据库 MySQL
【异常解决】缓存报错:Null key returned for cache operation (maybe you are using named params on classes withou
【异常解决】缓存报错:Null key returned for cache operation (maybe you are using named params on classes withou
740 0
|
7月前
|
Oracle 安全 Java
[Java] `JDK17` 模式变量 `Pattern variable` Variable ‘request‘ can be replaced with pattern variable
[Java] `JDK17` 模式变量 `Pattern variable` Variable ‘request‘ can be replaced with pattern variable
102 0
|
设计模式 uml
空对象模式(Null Object Pattern)
空对象模式(Null Object Pattern)不属于GoF设计模式,但是它作为一种经常出现的模式足以被视为设计模式了。其具体定义为设计一个空对象取代NULL对象实例的检查。NULL对象不是检查控制,而是反映一个不做任何动作的关系。这样的NULL对象也可以在数据不可用的时候提供默认的行为,属于行为型设计模式。
97 0
|
vr&ar
Testpattern
Testpattern
56 0
|
缓存 Java 关系型数据库
关于page Cache和memory mappped Files 和zero copy
关于page Cache和memory mappped Files 和zero copy
172 0
关于page Cache和memory mappped Files 和zero copy
|
自然语言处理 算法 数据挖掘
浅谈Single-Pass算法
Single-Pass算法又称单通道法或单遍法,是流式数据聚类的经典方法。对于依次到达的数据流,该方法按输入顺序每次处理一个数据,依据当前数据与已有类的匹配度大小,将该数据判为已有类或者创建一个新的数据类,实现流式数据的增量和动态聚类,适合对流数据进行挖掘,而且算法的时间效率高;不足之处主要表现在该方法具有输入次序依赖特性,即对于同一聚类对象按不同的次序输入,会出现不同的聚类结果。
244 0
|
Python
ConfigParser.MissingSectionHeaderError: File contains no section headers.
今天使用ConfigParser解析一个ini文件,报出如下错误: config.read(logFile) File "C:\Python26\lib\ConfigParser.py", line 286, in read self.
5720 0
|
存储 缓存 算法
我们还需要Page Cache么?
作者:齐江 杨艇艇 马涛
1112 0