MySql与Redis延迟双删策略


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点的并发的情况下如何保证双写一致性?中的最终解决方案


文章作者: 王子
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 王子 !
评论
  目录