首页 > 数据库技术 > 详细

redis和mysql结合数据一致性方案

时间:2021-02-20 12:00:54      阅读:23      评论:0      收藏:0      [点我收藏+]

缓存读:

缓存由于高并发高性能,已经被广泛的应用。在读取缓存方面做法一致。流程如下:

技术分享图片

写缓存:

1.先更新数据库,再更新缓存

2.先更新数据库,再删除缓存。

(1).先更新数据库,再更新缓存

这套方案,基本不推荐使用。

原因一:(线程安全角度)同时请求A和请求B进行更新操作,会出现。

  • (1)线程A更新了数据库
  • (2)线程B更新了数据库
  • (3)线程B更新了缓存
  • (4)线程A更新了缓存

由于网络原因出现A更新缓存比B慢,这就导致了脏数据,因此不考虑。

原因二:(业务场景)

  • (1)如果你是一个写数据库场景比较多,而读数据场景比较少的业务需求,采用这种方案就会导致,数据压根还没读到,缓存就被频繁的更新,浪费性能。
  • (2)如果你写入数据库的值,并不是直接写入缓存的,而是要经过一系列复杂的计算再写入缓存。那么,每次写入数据库后,都再次计算写入缓存的值,无疑是浪费性能的。显然,删除缓存更为适合。

总结:不建议使用该种 解决方案。

(2).先更新数据库,再更新缓存

方案存在的问题?

假设有两个请求,一个请求A做查询操作,一个请求B做更新操作。会有如下情况发生:

  • 缓存刚好失效
  • 请求A查询数据库,得到一个旧值
  • 请求B将新值写入数据库
  • 请求B删除缓存
  • 请求A将查询的旧值写入缓存ok

如上情况,会发生脏数据。

在数据库做读写分离的情况下,如果出现网络延迟,写库同步读库的时候,另外一个线程读取读库旧数据,就会对发生脏数据。

如何解决?

采用延时双删模式:

  • 先淘汰缓存
  • 再修改数据库
  • 休眠1(n)秒,再次淘汰缓存,可以将由于网络问题造成的缓存脏数据再次删除。

延迟1秒会造成整体吞吐量降低,可以采用异步方式处理。

如果第二次删除,删除失败怎么办?

提供重试机制

消息队列异步补偿机制:

技术分享图片

如果觉得如上方案对代码的侵入性太大,可以代用如下方案。

订阅mysql的binlog日志:

技术分享图片

订阅mysql的binlog程序有现成的中间件canal。

 

参考:https://zhuanlan.zhihu.com/p/59167071

 

redis和mysql结合数据一致性方案

原文:https://www.cnblogs.com/wingfirefly/p/14419728.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!