保证Redis与MySQL中的数据双写一致性 | 笔记

参考文章地址:如何实现Redis和Mysql中数据双写一致性
【Redis】所以延迟双删有啥用
延时双删实现MySQL和Redis的数据一致性

在学习苍穹外卖的时候,为了保持数据的一致性,当时教的方法是在每次进行数据库的操作之前就先删除Redis中对应的数据。原以为这确实是个好方法,今看到这篇公众号文章,又有了更深刻的了解,随记下笔记。

问题原因:
如果只是在每次操作前进行Redis的删除操作,这样的方式不一定每次都奏效。如果遇到了网络拥塞,那么删除了Redis中的数据库,需要过一段时间才能更新MySQL中的数据,那么在这段时间内如果有查询操作,那么又将出现数据不一致的情况。1

解决
虽然苍穹外卖中推荐的是先删后更,但是有的文章也会推荐使用先更后删,采用Cache Aside(旁路缓存)。先更后删也会存在数据不一致性的问题,只是相对出现的概率性不高2。如果要彻底解决这个问题就需要加锁,而这样做就会导致效率变低,所以还是需要看具体的业务要求,选取合适的解决策略。所以,Redis最好适用于多读少些的场景下。

1、缓存延迟双删
针对先删后更进行改良。

  1. 删除缓存
  2. 更新数据库
  3. 睡眠一段时间
  4. 再删除缓存

根据业务需要设置休眠时间,目的是为了删除请求造成的脏读数据。只能提高相对的保持数据一致性的能力。因为在休眠期间还是可能存在数据不一致的可能。

为什么要设置休眠时间:因为线程是交替进行的,A删了缓存 想要更新数据库的时候,这次是B可能查到了旧的数据,然后还没更新,又到A去操作数据库,然后又删除缓存,B再去更新数据,那么又数据不一致了。通过设置休眠时间,就可以保证在一定时间后数据是一致的。虽然中间有一些脏读数据,比起整体应该是可以接收的。

再加强:还可以给缓存设置过期时间,双延迟删除+过期时间来保持最终数据的一致性。只是会增加时耗。

2、删除重试
如果不是加锁,其他的策略都有可能造成数据不一致性,毕竟考虑极端情况就是删除缓存操作失效了。所以引入删除重试机制。
有通过消息队列进行,但是会业务代码造成入侵。

1.更新数据库
2.数据库将操作信息写入binlog日志中
3.订阅程序提取出所需要的数据以及key(通过cancal监听和执行删除操作,以及重新操作。)
4.一段非业务代码,获取该消息
5.尝试删除缓存操作,如果删除失败 - > 6
6.将消息发送至消息队列
7.重新从消息队列中获得该数据,重新操作。

会增加复杂度,但是能更好的保障数据的一致性。

总结:

性能要求高,数据一致性要求没有那么高得时候,还是采用先更后删的策略。
数据一致性要求高,且性能有一定容忍度的时候,采取双延迟删除的策略。
数据一致性要求再高一些,采取删除重试的策略。
最极端就是加锁,但是一般不会采取。


  1. Redis中的数据与MySQL中的数据不一样。 ↩︎

  2. 缓存的写入速度远大于数据库的写入,故此很少存在:A还在进行缓存的写入,而B完成了数据库到缓存的写入。 ↩︎

  • 5
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值