美文网首页
mysql与redis的双写一致性方案设计

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

作者: lcarrotp | 来源:发表于2022-04-26 03:30 被阅读0次

    参考:

    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、成熟的技术方案?

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

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

    延时双删变体:

    • 缓存删除重试机制,将删除失败的key放入mq,从mq中将删除失败的key拿出来重新删除,并不断重复这个操作,直至key删除成功;

    • binlog异步删除机制(cancal),上述删除重试机制,虽然能解决删除失败的问题,但是会导致重试机制代码会与业务代码耦合性大大提高,该重试机制会导致业务代码存在大量从代码。失败重试机制作为公共功能,理应从业务代码抽离,单独处理。

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

    image.png

    相关文章

      网友评论

          本文标题:mysql与redis的双写一致性方案设计

          本文链接:https://www.haomeiwen.com/subject/suqcyrtx.html