Redis 缓存的数据一致性问题

Redis 缓存的数据一致性问题

系统加入缓存后,在一些极端情况下,就会出现缓存和数据库的数据不一致,导致读取到脏数据

首先需要确定一点的是不可能做到绝对的一致性,原因是 redis 和数据库本身就是两个系统,他们之间没法实现事务,无法保证原子性,在高并发的情况下,不管是先更新数据库,还是缓存,总会有一个时刻 redis 和 数据库的数据时不一致的,如果业务要求高一致性就不要上 redis

更新策略

当数据发生变化时,对数据库和缓存的操作如下

更新操作

对数据库的更新操作:

  • 直接更新数据

对缓存的操作:

  • 删除缓存,等下次访问数据时再从数据库中获取数据,添加到缓存

  • 直接更新缓存

更新顺序

缓存和数据库更新顺序:

  • 先数据库后缓存

  • 先缓存后数据库

所以总共有 4 种更新策略

四种策略

先更新数据库,后删除缓存

时间线程A线程B数据库缓存
1缓存失效v1null
2读取数据库为v1v1null
3更新数据库为v2v2null
4删除缓存v2null
5写入缓存v1v2v1

先更新数据库,后更新缓存

时间线程A线程B数据库缓存
1v0v0
2更新数据库为v1v1v0
3更新数据库为v2v2v0
4更新缓存为v2v2v2
5更新缓存为v1v2v1

先删除缓存,后更新数据库

时间线程A线程B数据库缓存
1删除缓存v1null
2缓存失效v1null
3读取数据库v1null
4写入缓存v1v1v1
5更新数据库为v2v2v1

先更新缓存,后更新数据库

时间线程A线程B数据库缓存
1v0v0
2更新缓存为v1v0v1
3更新缓存为v2v0v2
4更新数据库为v2v2v2
5更新数据库为v1v1v2

如何选择

排除更新缓存策略

首先排除先更新缓存,后更新数据库;

  • 我们可以发现前三种最终都是缓存为旧值,数据库为新值;

    而对于最后一种策略而言,它最终缓存为新值,数据库为旧值,而缓存中的数据没有持久化,是易丢失的,这种情况下十分危险,所以也是基本不推荐的

再者排除先更新数据库,后更新缓存,原因主要是从浪费性能方面考虑:

  1. 如果是需要写入操作多,读取操作少的业务,那么,会出现数据还没被读取过就又被更新了,浪费性能;
  2. 写入缓存的值可能是经过计算后写入的,那么频繁修改缓存也是一种性能浪费;
“先数据库,后缓存” 和 “先缓存,后数据库”

我们需要考虑两种策略出现数据不一致的可能性

实现我们要明确在 缓存删除和写入的速度是 要小于 数据库查询和更新的速度,所以主要的耗时较大的是在数据库查询和更新上;

数据库的查询一般是快于数据库更新

先缓存,后数据库
时间线程A线程B数据库缓存
1删除缓存v1null
2缓存失效v1null
3读取数据库v1null
4写入缓存v1v1v1
5更新数据库为v2v2v1

使用该策略时,数据不一致主要是由 线程 A 完成更新数据库 晚于 线程 B 读取数据库写入缓存 导致的,而数据库查询就是快于数据库更新的,所以这种情况发生的可能性是比较大的

先数据库,后缓存
时间线程A线程B数据库缓存
1缓存失效v1null
2读取数据库为v1v1null
3更新数据库为v2v2null
4删除缓存v2null
5写入缓存v1v2v1

使用该策略时,导致数据不一致的原因是 线程 A 的写入缓存v1 晚于 线程 B 的删除缓存,而读取数据库并写入缓存 一般是要比 更新数据库删除缓存快的,步骤5要晚于步骤4执行的可能性较低

总结

  1. 无论哪一种策略都会引起数据不一致,验证了我们一开始说的结论

  2. 先更新缓存,后更新数据库不可取

  3. 更新缓存操作性能浪费,不推荐

  4. 选择先更新数据库后删除缓存策略,出现数据不一致的可能性低

其他引起数据不一致的情况

以上的讨论都是建立在每项操作都可以执行成功的前提下,但是如果出现删除或更新缓存失败时,我们不采取异常处理的话也是会出现数据不一致的;

解决方法(待完善)

可以启动一个线程重复执行删除缓存操作直到成功,具体似乎是使用消息队列(本人还没学习到,此处先不写了)

参考文章

http://www.kokojia.com/article/45871.html

https://blog.csdn.net/hukaijun/article/details/81010475

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值