MySql与Redis延迟双删策略

本文探讨了MySql与Redis数据同步的两种策略:先更新DB后删除缓存和先删除缓存再更新DB。重点解析了延迟双删策略的优缺点,推荐了在大多数场景下采用先更新DB结合MQ异步删除缓存的方式,以保证数据一致性。还介绍了双写一致性协议、分布式锁和行锁在一致性问题上的应用。
摘要由CSDN通过智能技术生成

个人博客

欢迎访问个人博客: https://www.crystalblog.xyz/

备用地址: https://wang-qz.gitee.io/crystal-blog/

1. MySql与Redis如何实现数据同步问题?

见第4点先更新db再删除缓存 or 先删除缓存再更新db的详解.

2. 什么是缓存延迟双删策略?

见第4点先删除缓存再更新db中的延迟双删方案

3. 为什么不建议使用延迟双删?

见第4点先删除缓存再更新db中的方案选择

4. 先更新db再删除缓存 or 先删除缓存再更新db?

先更新db, 再删除缓存, 会结合MQ异步删除缓存, 延迟比较高.

伪代码:

updateDB(user); // 更新db数据
sendMqMsgToDeleteRedis(key); // 先删除缓存

如果更新db成功, 但是删除缓存失败如何处理? MQ重试机制, 保证该message消息必须消费成功.

先删除缓存, 再更新db, 延迟低.

伪代码:

deleteRedis(key); // 先删除缓存
updateDB(user); // 更新db数据

如果A请求删除缓存成功, 但是更新db失败, 其他请求过来又重新查询db的旧数据存入到Redis缓存中, 会导致Redis与mysql数据一致性问题. 如何解决呢, 初始解决方案—延迟双删

延迟双删方案

T1线程线删除缓存再更新db , T1线程更新db完成之前T2线程如果读取到db旧的数据, 会再把旧的数据写入Redis缓存, 此时T1线程延迟一段时间后再删除Redis缓存操作. 当其他线程再读取缓存为null时会查询db最新数据重新进行缓存, 保证了Mysql和Redis缓存的数据一致性.

所以, T1线程sleep的时间, 就需要大于T2线程读取数据再写入Redis缓存的时间.

延迟时间如何确定?

在业务程序运行时, 统计业务逻辑执行读取数据和写Redis缓存的操作时间, 以此为基础进行估算. 因为这个方案会在第一次删除缓存值后, 延迟一段时间再次进行删除, 所以称为"延迟双删" . — 不推荐大家使用延迟双删.

伪代码:

deleteRedis(key); // 先删除缓存
updateDB(user); // 更新db数据, 事务未完成
sleep(seconds); // 延迟一段时间,待其他线程读取db旧数据缓存到Redis完成
deleteRedis(key); // 再删缓存

延迟双删方案方案如何选择?

绝大多数场景都会将Redis作为只读缓存:

(1) 先删除缓存, 再更新db. 更新db完成之前, 其他线程在读取缓存时发现数据为null, 会将旧数据重新缓存到Redis中, 导致其他线程一直查询的数据为旧的数据. 需要考虑延迟双删问题, 延迟双删的时间不是很好控制.

(2) 也可以先更新db再结合MQ异步删除Redis缓存; 因为先更新db, 再删除缓存, 其他线程在读过程中只是短暂读取到数据(旧数据), 只要及时将该缓存key删除, 其他线程就可以读取到最新的数据.

所以推荐使用先更新db, 再删除缓存.

5. 什么是双写一致性协议?

更新完db后, 同步更新Redis缓存; 更新db操作与更新Redis缓存是一样的, 不是直接删除Redis缓存key, 俗称 “双写”.

6. 并发的情况下如何保证双写一致性?

请添加图片描述
t1线程先更新db, 再更新Redis缓存; 如果t1线程在更新Redis缓存完成之前, t2线程优先完成Redis缓存的更新, 然后t1线程再完成Redis缓存的更新, 导致db数据xiaojun和Redis缓存的数据mayikt不一致问题.

导致不一致的时间线:

t1线程更新db – t2线程更新db – t2线程更新缓存 – t1线程更新缓存.

理想结果的时间线:

t1线程更新db – t1线程更新缓存-- t2线程更新db – t2线程更新缓存.

初始解决方案:

可以将更新db的事务放到更新完缓存后提交(Mysql行锁保证数据一致性). 但是性能很低.

伪代码:

begin(transaction); // 开启事务
updateDB(user); // 更新db
updateRedis(key); // 更新缓存
commit(transaction); // 提交或回滚事务

进阶解决方案:

zookeeper等分布式锁.

最终解决方案:

推荐MQ异步双写, 没有锁的竞争, 效率比较高. 但是会有延迟问题. 能够保证最终一致性.

可以使用canal + kafka + 消息顺序一致性

请添加图片描述

7. 分布式锁如何解决双写一致性问题?

见第6点的并发的情况下如何保证双写一致性?中的进阶解决方案

8. MySql行锁机制如何解决双写一致性问题?

见第6点的并发的情况下如何保证双写一致性?中的初始解决方案

9. 为何说分布式情况下强一致性几乎很难实现?

保证最终一致性, 见第6点的并发的情况下如何保证双写一致性?中的最终解决方案

  • 9
    点赞
  • 36
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值