代码改变世界

Cache Aside Pattern

2019-02-13 11:58  Tony、  阅读(427)  评论(0编辑  收藏  举报

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沈剑 架构师之路