首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >缓存和DB中数据一致性

缓存和DB中数据一致性

作者头像
用户5325874
发布2020-01-16 17:48:28
1.9K0
发布2020-01-16 17:48:28
举报

缓存和DB中数据一致性

淘汰还是更新

一般来说,是淘汰

  • 一般来说,修改的成本会高于淘汰的成本
    • 修改的话,假如存的是json字符串,需要先将数据反序列化,然后修改数据,然后序列化,再存入redis。修改的代价高,但是少一次cache miss
    • 淘汰的话,就将数据置为无效,但是多一次cache miss
  • 修改缓存,在并发写的时候,可能出现数据不一致
    • 比如说请求1 先写数据库,然后请求2写数据库
    • 接着请求2更新缓存,请求1更新缓存
    • 这就造成数据库是请求2的修改结果,缓存是请求1的修改结果
  • 一般的模式为:
    • 更新了数据,就直接淘汰掉缓存

顺序问题

是先操作缓存,还是先操作DB?

先操作缓存,再操作DB

先淘汰缓存成功,后更新DB失败(比如说服务挂了),不会造成不一致。

但是缓存淘汰了以后,主库还没有同步到从库,又有一个读请求,把旧的数据读到缓存,也会造成不一致。

这种情况下不一致概率是比较高的,因为一般情况下读请求远远高于写请求,当淘汰了缓存之后,在更新DB之前很有可能有读请求把从库的旧数据读到缓存中,从而造成不一致。

不过对于这种情况,有以下两种办法:

  • 给缓存设置过期时间,能达到最终一致性
  • 监听主库bin log,当主从同步完成,再淘汰一次缓存

但是这样子代价就比较高了,架构变得复杂。

先操作DB,后操作缓存

先更新DB,后更新缓存。 假如更新完DB后,服务挂了,没有更新缓存,缓存过期后,经历一次缓存miss,那么数据将达到最终一致。

DB主从延迟导致的缓存不一致

背景

缓存与数据库不一致

image-20191108231125166
image-20191108231125166

如上图,发生的场景也是,写后立刻读:

(1+2)先一个写请求,淘汰缓存,写数据库

(3+4+5)接着立刻一个读请求,读缓存,cache miss,读从库,写缓存放入数据,以便后续的读能够cache hit(主从同步没有完成,缓存中放入了旧数据)

(6)最后,主从同步完成

导致的结果是:旧数据放入缓存,即使主从同步完成,后续仍然会从缓存一直读取到旧数据。

可以看到,加入缓存后,导致的不一致影响时间会很长,并且最终也不会达到一致。

方案

image-20191108231456000
image-20191108231456000

如上图所述,在并发读写导致缓存中读入了脏数据之后:

(6)主从同步

(7)通过工具订阅从库的binlog,这里能够最准确的知道,从库数据同步完成的时间

画外音:本图画的订阅工具是DTS,也可以是cannal订阅和分析binlog

(8)从库执行完写操作,向缓存再次发起删除,淘汰这段时间内可能写入缓存的旧数据

(这样子还是在短时间内可能存在缓存和DB不一致,但是能达到最终一致性)

Cache Aside Pattern

Cache Aside Pattern是缓存经典实践方式,分为读实践、写实践。

对于读请求

  • 先读缓存
  • 缓存命中,直接返回数据
  • 缓存未命中,则查询DB
  • 将数据set到内存

对于写请求

  • 先更新数据库
  • 后淘汰缓存

总结

  • 先更新DB,再更新缓存
  • 尽量淘汰缓存
  • 可以采用纯内存数据库,然后异步更新到DB(要求高可用)

参考

缓存一致性

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 缓存和DB中数据一致性
    • 淘汰还是更新
      • 顺序问题
        • DB主从延迟导致的缓存不一致
          • 背景
          • 方案
        • Cache Aside Pattern
          • 总结
            • 参考
            领券
            问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档