Redis的 延时双删以及数据一致性

13 篇文章 0 订阅
1 篇文章 0 订阅

为了减轻数据库的压力,我们会将更新频率较低,查询频率较高的接口的数据缓存到 Redis 中:

  • 对于查询接口,我们会让请求先到 Redis,如果命中则返回结果;如果缓存失效,则从数据库查询,再写入到缓存中
  • 对于更新接口,我们使用缓存双删策略,保证数据库与 Redis 缓存数据的一致性

为了保证数据库与缓存的一致性,常用的缓存更新策略有:

  • 先更新数据库,再更新缓存
  • 先删除缓存,再更新数据库
  • 先更新数据库,再删除缓存

方案一:先更新数据库,再更新缓存

假设有请求 A 和请求 B 同时执行更新操作,那么有可能会出现:

  1. 线程 A 更新了数据库
  2. 线程 B 更新了数据库
  3. 线程 B 更新了缓存
  4. 线程 A 更新了缓存

线程 A 更新缓存应该比线程 B 更新缓存要早才对,但因为网络等原因,就会导致这种脏数据。

方案二:先删除缓存,再更新数据库

假设有请求 A 进行更新操作,另一个请求 B 进行查询操作,那么有可能会出现:

  1. 线程 A 进行更新操作前,先删除了缓存
  2. 线程 B 查询发现缓存不存在
  3. 线程 B 查询数据库的旧值
  4. 线程 B 将旧值写入到缓存
  5. 线程 A 执行更新,将新值写入到数据库

这样便出现了数据库与缓存不一致的情况。

方案三:先更新数据库,再删除缓存

我们来看一下该方案导致的并发问题,请求 A 进行查询操作,请求 B 执行更新操作:

  1. 缓存刚好失效
  2. 线程 A 查询数据库,得到一个旧值
  3. 线程 B 将新值写入到数据库
  4. 线程 B 删除缓存
  5. 线程 A 将旧值写入到缓存

这样就会导致出现脏数据。

该方案虽然存在并发问题,但是出现上述情况的概率是极低的,也有一些企业在使用这种方案。

回过头,我们来看一下本项目使用的延迟双删策略:

延迟双删的流程为:

  1. 先删除缓存
  2. 再写数据库
  3. 休眠一段时间,再淘汰缓存

回顾一下方案二,即先删除缓存,再更新数据库可能造成数据库与缓存不一致的情况:

假设有请求 A 进行更新操作,另一个请求 B 进行查询操作,如果使用缓存双删策略:

  1. 线程 A 进行更新操作前,先删除了缓存
  2. 线程 B 查询发现缓存不存在
  3. 线程 B 查询数据库的旧值
  4. 线程 B 将旧值写入到缓存
  5. 线程 A 执行更新,将新值写入到数据库,执行 Thread.sleep(t)
  6. 线程 A 苏醒,再次将缓存中的值删除

这样就有效避免了数据库与缓存不一致的情况。

缓存双删的优点是大大降低了数据库与缓存不一致的概率的发生,缺点为一定程度上降低了吞吐量。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值