缓存数据一致性刷新方案


这里分享一下缓存和数据库数据一致性刷新的一些方案和实践。
主要从一下4个方面进行介绍和分享。

数据一致性介绍

  • 随着业务发展,数据需要添加副本以提高可行性;
  • 为减少db访问压力,需要进行读写分离;
  • 为提高接口响应时间,一般会将访问数据进行缓存;
  • 当然还有其他形式的数据,如存储与es搜索引擎以满足特定业务场景(此处主要讨论缓存数据一致性);

一些方案

  • 使用缓存的一些场景:
    • 面向用户的接口请求量大,使用缓存提升性能;
    • 数据强一致性场景(如 库存),直接操作数据库,展示类接口使用缓存;
  • 方案一:
    • 查询接口时无缓存数据进行缓存数据的写入;
    • 缓存失效时间使缓存自动失效;
    • 数据变动,根据对db从库的监听对缓存进行失效;
  • 方案二:
    • 查询接口时无缓存则获取缓存;
    • 缓存自动失效;
    • 数据变动触发缓存数据更新;

遇到的问题和解决

  • 问题:从数据库变动发出消息失效缓存,写入缓存时读取其他从库,导致写入脏数据;
    • 解决:所有的从库数据变动都去发送触发缓存失效的消息;
      多线程缓存读写1
  • 问题:过期缓存删除存在隐患,无法预知当前是否有线程已持有过期数据正要插入(缓存的读取不是原子操作);如下图:
    • 解决:采用如下图的方案:相关说明如下
      多线程缓存读写2
    • 先删除缓存后删除db数据,防止当前网站线程crash引起数据不一致;
    • 原子操作前判断缓存是否命中,命中则直接返回,防止热点数据引起的缓存击穿;
    • 减小缓存数据的颗粒,减小此处锁的颗粒,降低锁开销,锁持有的时间就是一次数据库访问的时间;

一些思考和总结

  • 任何技术方案都需要根据具体的业务场来考虑,比如缓存方案中,数据变动是去时缓存失效还是刷新缓存,就是可以考虑多个方面;
  • 缓存多大范围的数据?
  • 数据的热点程度?

文章作者: Xudong Jiang
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 Xudong Jiang !
 上一篇
java容器-列表和队列 java容器-列表和队列
今天介绍一些java内的容器-列表和队列,有些容器会在后续案例中更详细介绍 列表和队列 ArrayList 实现了Iterable接口,可迭代, 内部有一个数组elementData,一般有些预留空间,有整数size记录实际元素个数; 添加
2019-11-05
下一篇 
java容器-堆和优先队列 java容器-堆和优先队列
今天介绍一些java内的容器-堆和优先队列,有些容器会在后续案例中更详细介绍 堆 是完全二叉树,给定任意一个节点,可以根据其编号直接快速计算出其父节点和孩子节点编号 根据顺序分为两种堆:一种是最大堆,另一种是最小堆 可以实现优先级队列,解决
2019-10-16
  目录