缓存数据库更新策略

Cache Aside Pattern(旁路缓存模式)
对于读请求
先读cache,再读db
如果,cache hit,则直接返回数据
如果,cache miss,则访问db,并将数据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)写请求淘汰了缓存
(2)写请求操作了数据库(主从同步没有完成)
(3)读请求读了缓存(cache miss)
(4)读请求读了从库(读了一个旧数据)
(5)读请求set回缓存(set了一个旧数据)
(6)数据库主从同步完成
导致,数据库与缓存的数据不一致。

其实我认为就算没有主从同步这个问题,只有一台数据库,也会出现数据不一致的情况:
(1)写请求淘汰了缓存
(2)此时进来一个读请求,将旧的数据set进缓存
(3)写请求操作了数据库
这种情况的概率是很大的,因为大多数情况下的都是读多写少的场景。

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

Cache Aside Pattern方案存在什么问题?
从并发角度
比如,一个是读操作,但是没有命中缓存(缓存刚好到期),就会到数据库中取数据。而此时来了一个写操作,写完数据库后,让缓存失效,然后之前的那个读操作再把老的数据放进去,所以会造成脏数据。
这个案例理论上会出现,但实际上出现的概率可能非常低,因为这个条件需要发生在读缓存时缓 存失效,而且有一个并发的写操作。实际上数据库的写操作会比读操作慢得多,而且还要锁表, 而读操作必需在写操作前进入数据库操作,又要晚于写操作更新缓存,所有这些条件都具备的概率并不大。

所以不能完全避免并发导致的数据不一致问题,只能从概率上保证。

分布式事务角度
如果先操作数据库,再淘汰缓存,在原子性被破坏时:
(1)修改数据库成功了
(2)淘汰缓存失败了
导致,数据库与缓存的数据不一致。

但是
Cache Aside Pattern操作缓存失败,可以通过重试加打日志发现补救,也可以通过canal或者databus走kafka来失效缓存,基本能解决调缓存失败的情况。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • PS:转载自《架构师之路》,觉得受益匪浅,故收录之 缓存误用 缓存,是互联网分层架构中,非常重要的一个部分,通常用...
    Huang远阅读 11,382评论 4 27
  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 135,079评论 19 139
  • 理论总结 它要解决什么样的问题? 数据的访问、存取、计算太慢、太不稳定、太消耗资源,同时,这样的操作存在重复性。因...
    jiangmo阅读 2,961评论 0 11
  • 关于Mongodb的全面总结 MongoDB的内部构造《MongoDB The Definitive Guide》...
    中v中阅读 32,056评论 2 89
  • 哈哈哈,昨晚看了这: 001、那些狗血的剧情真不适合太感性的人看,看了以为是真的。 002、真心爱,坦白沟通呀,折...
    小苏Amy阅读 161评论 0 1