老师你好!!!
来源:3-23 缓存数据双写一致

twodog二狗
2021-12-28
老师你好,这是我结合网上的资料,对缓存双删做的总结:
为了减轻数据库的压力,我会将更新频率较低,查询频率较高的接口的数据缓存到 Redis 中:
- 对于查询接口,我们会让请求先到 Redis,如果命中则返回结果;如果缓存失效,则从数据库查询,再写入到缓存中
- 对于更新接口,我们使用缓存双删策略,保证数据库与 Redis 缓存数据的一致性
为了保证数据库与缓存的一致性,常用的缓存更新策略有:
- 先更新数据库,再更新缓存
- 先删除缓存,再更新数据库
- 先更新数据库,再删除缓存
方案一:先更新数据库,再更新缓存
假设有请求 A 和请求 B 同时执行更新操作,那么有可能会出现:
- 线程 A 更新了数据库
- 线程 B 更新了数据库
- 线程 B 更新了缓存
- 线程 A 更新了缓存
线程 A 更新缓存应该比线程 B 更新缓存要早才对,但因为网络等原因,就会导致这种脏数据。
方案二:先删除缓存,再更新数据库
假设有请求 A 进行更新操作,另一个请求 B 进行查询操作,那么有可能会出现:
- 线程 A 进行更新操作前,先删除了缓存
- 线程 B 查询发现缓存不存在
- 线程 B 查询数据库的旧值
- 线程 B 将旧值写入到缓存
- 线程 A 执行更新,将新值写入到数据库
这样便出现了数据库与缓存不一致的情况。
方案三:先更新数据库,再删除缓存
大家可以先读一下这篇文章《Cache-Aside patter》
我们来看一下该方案导致的并发问题,请求 A 进行查询操作,请求 B 执行更新操作:
- 缓存刚好失效
- 线程 A 查询数据库,得到一个旧值
- 线程 B 将新值写入到数据库
- 线程 B 删除缓存
- 线程 A 将旧值写入到缓存
这样就会导致出现脏数据。
该方案虽然存在并发问题,但是出现上述情况的概率是极低的,也有一些企业在使用这种方案。
回过头,我们来看一下本项目使用的延迟双删策略:
延迟双删的流程为:
- 先删除缓存
- 再写数据库
- 休眠一段时间,再淘汰缓存
回顾一下方案二,即先删除缓存,再更新数据库可能造成数据库与缓存不一致的情况:
假设有请求 A 进行更新操作,另一个请求 B 进行查询操作,如果使用缓存双删策略:
- 线程 A 进行更新操作前,先删除了缓存
- 线程 B 查询发现缓存不存在
- 线程 B 查询数据库的旧值
- 线程 B 将旧值写入到缓存
- 线程 A 执行更新,将新值写入到数据库,执行
Thread.sleep(t)
- 线程 A 苏醒,再次将缓存中的值删除
这样就有效避免了数据库与缓存不一致的情况。
缓存双删的优点是大大降低了数据库与缓存不一致的概率的发生,缺点为一定程度上降低了吞吐量。
写回答
1回答
-
风间影月
2021-12-28
挺好的666
00
相似问题