如何保证缓存与MySQL双写一致(Redis如何保证双写一致性问题)

本文探讨了Redis中的双写一致性问题,介绍了修改和删除操作可能带来的数据不一致,提出使用延迟双删策略解决并发问题。最终解决方案是结合消息队列和延迟删除,但并不能完全避免所有情况,只能极大降低不一致发生的概率。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


​👑作者主页:Java冰激凌


什么是Redis双写一致性问题

所谓的双写一致问题是指,当有数据修改时,要保证缓存和数据都能一起及时的更新,否则就会出现双写不一致的问题

如何解决?

首先我们可以思考 如果要解决这个问题 无非要从两个大类来出发 无非就是 “修改” || “删除”
对应的方案如下
修改
1. 先修改数据库数据,再去修改Redis数据
2. 先修改Redis数据,再修改数据库数据
删除
1. 先更新数据库数据,再删除Redis数据
2. 先删除Redis数据,再更新数据库数据
然而,这些方法看似都是可以解决问题的,但是~ 因为我们的操作是分为了两步的,也就是代表 这并非是一个原子性的操作,所以可能会出现掉电的问题或者是服务器崩溃的问题
修改
1. 先修改数据库数据,再去修改Redis数据(掉电) -》 会造成数据双写不一致的问题
2. 先修改Redis数据,再修改数据库数据(掉电) -》 会造成数据双写不一致的问题
删除
1. 先更新数据库数据,再删除Redis数据(掉电) -》 会造成数据双写不一致的问题
2. 先删除Redis数据,再更新数据库数据(掉电) -》 不会造成不一致问题
具体分析一下

  1. 先修改数据库数据,然后在修改Redis数据中的时候发生了掉电,导致Redis中的数据是未发生修改的,所以当服务器再次重启的时候,就会造成Redis与数据库中的数据已不一致的问题
  2. 先修改Redis数据,再修改数据库数据中的时候发生了掉电,导致数据库中的数据是未更新的状态,这也造成了数据不一致的问题
  3. 先更新数据库数据,再删除Redis数据的时候发生了掉电,那么服务器重启后,Redis中存储的仍旧是旧数据,数据库中存储的是新数据,如此还是会导致数据不一致的问题
  4. 先删除Redis数据,再更新数据库数据的时候发生了掉电,此时重启服务器后,Redis中是没有数据的,所以客户端请求该数据的时候就会去数据库中查询,然后缓存到Redis中,此时是可以保证我们双写一致的,也就可以解决我们的数据双写不一致的问题

但是!!!

使用第四种方案仍旧存在问题的,在我加入并发一起去思考之后,发现了新的问题
假设我们现在有两个线程
在这里插入图片描述
首先线程1去删除缓存,在删除缓存后到达了下一个时间片,线程2发现Redis中并没有数据(因为此时数据已经被删除了)所以会直接去数据库中查询,那么此时线程2会得到旧值,然后准备将数据库中的数据更新到缓存中,此时很不巧,线程2的时间片用完了,然后线程1再次拿到了时间片,线程1继续执行更新数据库中的值,然后再去添加缓存到Redis中,然后线程1完成工作,放弃时间片,线程2拿到时间片后,最后讲旧值更新到缓存中,此时就出现了问题 最后的结果是 Redis中存储的仍旧是旧值,但是在数据库中存储的是新值,此时又再次导致了双写不一致的问题

解决方案 延迟双删

解决这个并发问题,可以使用延迟双删的策略,也就是需要删除两次缓存,并在第二次删除是需要稍微等一会儿再执行删除策略,这样能够尽量的避免并发问题

但是????

尊嘟假嘟,保证数据库和缓存的双写一致的最终方案是使用:消息队列 + 延迟双删策略
尊嘟 但是还有细节需要考虑
提一个问题
延迟双删是否可以完全解决双写一致问题呢?
答案:其实是不一定的,这样只能最大限度的去解决双写不一致的问题
因为CPU是操作系统做随机分配执行的,并且在并发中,存在了更多的不确定因素,这些种种原因导致了可能会出现更多的执行过程,但是我们可以肯定的是,以上的这些方案,可以解决98%以上的双写不一致的问题

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Java冰激凌

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值