mysql与redis的双写一致性方案设计

2022-04-26  本文已影响0人  lcarrotp

参考:

https://juejin.cn/post/7074395743213060133

个人学习总结及分享,和而不同,相帮共勉

1、问题:

  1. 为什么会出现数据双写一致性问题?
    首先介绍下redis与mysql的双写工作场景
image.png

假设数据库有a=1,缓存a=1,现有两个线程A、B,A线程更新a=2,B线程更新a=3
具体操作时间线如下,最终导致缓存中a=2,而数据库中a=3,数据存在明显不一致的情况。

image.png

根本原因,是多线程并发操作导致数据库和缓存数据未及时更新

2、是更新缓存or删除缓存,是先操作缓存还是先操作数据库?

根据问题,衍生出三种更新策略:

  1. 先更新数据库,再更新缓存 or 先更新缓存,再更新数据库,这种情况,由于是更新操作,由于多线程操作,并不能保证执行缓存操作时,线程的修改数据的先后顺序,若缓存未设置过期时间很容易产生脏数据,且更新缓存势必引入不必要的更新逻辑(\color{red}{除非那种强依赖缓存的高并发场景}),否则通常不予考虑。

  2. 先删除缓存,再更新数据库,假设两个线程A,B,数据库、缓存初始值a=1,A写操作更新a=,2的值,B读操作。具体操作时间线如下图,最终导致数据不一致,只能等待下次数据更新或者缓存过期时间到,才更新缓存,保证数据最终一致性。

image.png
  1. 先更新数据库,再删除缓存,(业界普遍使用的方案)假设两个线程A,B,数据库、缓存初始值a=1,A写操作更新a=,2的值,B读操作。具体操作时间线如下图,最终导致数据不一致,但是数据不一致仅限于线程A还未删除缓存a前,间隔时间短。
image.png

3、成熟的技术方案?

核心方案:"延时双删”,通俗来讲就是删两次缓存,第一次,先更新数据库,在删除缓存。第二次,等待一段时间再删除一次缓存。

但是延时双删会存在一些问题,比如,删除失败如何解决,由于设置等待时间导致应用吞吐量下降如何解决?

延时双删变体:

基于以上考虑,业界推出基于binlog的异步删除策略,具体业务逻辑如下:

image.png
上一篇下一篇

猜你喜欢

热点阅读