Redis缓存和MySQL数据如何保持数据一致性(面试常问)

4 篇文章 0 订阅
2 篇文章 0 订阅

1.延时双删策略

1.1先更新redis缓存再更新mysql数据的问题

1.1.1第一个问题(两个操作有一个失败的情况):

这个操作分为两步,第一步更新缓存,第二步更新数据库,这两步操作不是原子性的,如果第一步成功,第二步失败会导致缓存是新数据,数据库是旧数据,反应到前端页面看起来是修改成功了,但是当缓存(新数据)失效后,从数据库拿数据(旧数据)重建缓存,缓存又是旧数据了。这样子数据不一致。

1.1.2第二个问题(并发情况下多线程操作的情况):

1.假如两个用户A,B同时改一个数据,A改为1,B改为2,
2.A线程先执行改缓存为1,B线程后执行改缓存为2,
3.但是B线程先执行改数据库为2,A线程后执行改数据库为1。
4.最终结果是,缓存数据是2,数据库数据是1。这样的话数据不一致。

1.2先更新mysql数据再更新redis缓存的问题

1.2.1第一个问题(两个操作有一个失败的情况):

情况跟1.1.1一样

1.2.2第二个问题(并发情况下多线程操作的情况):

情况跟1.1.2一样

1.3先删除redis缓存再更新mysql数据的问题

如果有 2 个线程要并发「读写」数据,可能会发生以下场景:
1.线程 A 要更新 a = 2(原值 a = 1)
2.线程 A 先删除缓存
3.线程 B 读缓存,发现不存在,从数据库中读取到旧值(a= 1)
4.线程 A 将新值写入数据库(a = 2)
5.线程 B 将旧值写入缓存(a = 1)
6.最终 X 的值在缓存中是 1(旧值),在数据库中是 2(新值),发生不一致。

1.4先更新mysql数据再删除redis缓存的问题

依旧是 2 个线程并发「读写」数据:
1.缓存中 a 不存在(数据库 a = 1)
2.线程 A 读取数据库,得到旧值(a = 1)
3.线程 B 更新数据库(a = 2)
4.线程 B 删除缓存
5.线程 A 将旧值写入缓存(a = 1)
6.最终 a 的值在缓存中是 1(旧值),在数据库中是 2(新值),也发生不一致。

1.5 延时双删

延迟双删,如果是写操作,我们先把缓存中的数据删除,然后更新数据库,最后再延时删除缓存中的数据可以避免缓存是旧数据,但是其中这个延时多久不太好确定。

2.异步通知保证数据的最终一致性

更新完数据库后使用rabbitmq异步通知redis服务更新缓存。保证更新数据库再更新缓存两步执行成功。

3.基于Canel的异步通知

采用的阿里的canal组件实现数据同步:不需要更改业务代码,部署一个canal服务。canal服务把自己伪装成mysql的一个从节点,当mysql数据更新以后,canal会读取binlog数据,然后在通过canal的客户端获取到数据,更新缓存即可。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值