目录
Redis数据双写一致性
缓存可以提升性能,缓解数据库压力,但是同时缓存也会出现缓存和数据库数据不一致的问题。
如果数据不一致,就会导致应用在缓存中读取的不是最新的数据,
在不考虑并发的情况下,不论谁先谁后,都可以让两者保持一致。但现在我们需要重点考虑异常的情况,也就是“第一步成功、第二步失败”的情况。
无并发时可能存在的问题
1、先更新缓存,后更新数据库
如果缓存更新成功了,但数据库更新失败,那么此时缓存中是最新值,但数据库中是旧值,数据不一致。
2、先更新数据库,后更新缓存
如果数据库更新成功了,但缓存更新失败,那么此时数据库中是最新值,缓存中是旧值。之后的读请求读到的都是旧数据,只有当缓存失效后,才能从数据库中得到正确的值。
在并发的情况下,即使不发生异常,也容易
3、并发下 先删除缓存,后更新数据库
如果有 2 个线程要并发「读写」数据,可能会发生以下场景:
1、线程 A 要更新 X = 2(原值 X = 1)
2、线程 A 先删除缓存
3、线程 B 读缓存,发现不存在,从数据库中读取到旧值(X = 1)
4、线程 A 将新值写入数据库(X = 2)
5、线程 B 将旧值写入缓存(X = 1)
结果:数据不一致
4、并发下先更新数据库,后删除缓存
依旧是 2 个线程并发读写数据:
- 缓存中 X 不存在(数据库 X = 1)
- 线程 A 读取数据库,得到旧值(X = 1)
- 线程 B 更新数据库(X = 2)
- 线程 B 删除缓存
- 线程 A 将旧值写入缓存(X = 1)
结果:数据不一致
常用方案:延迟双删策略。
延时双删:
1、删除缓存
redis延时双删第一个删除是为了什么?
如果不删第一次的话,就相当于先更新库后删缓存,这种情况下如果删缓存失败了就会有一致性问题;而先删缓存再删库,删数据库失败了也就是多一次cache miss,
2、更新数据库
3.休眠一定时间
4、再次删除缓存
为什么要延时呢?因为 mysql 和 redis 主从节点数据不是实时同步的,同步数据需要时间。
数据工作的大致流程:
服务节点删除 redis 主库数据。
服务节点修改 mysql 主库数据。
服务节点使得当前业务处理 等待一段时间,等 redis 和 mysql 主从节点数据同步成功。
服务节点从 redis 主库删除数据。
当前或其它服务节点读取 redis 从库数据,发现 redis 从库没有数据,从 mysql 从库读取数据,并写入 redis 主库。
标签:缓存,双删,redis,数据库,Redis,更新,线程,架构师,数据
From: https://www.cnblogs.com/xieshier/p/16706265.html