缓存延迟双删的两种策略

策略A:先删 → 更新 DB → 延迟再删(经典版)

复制代码
t1: 请求A 删除缓存
t2: 请求B 查缓存 miss,读到旧值
t3: 请求A 更新 DB 完成
t4: 请求B 把旧值回填缓存  ← 脏数据
t5: 延迟 500ms 后再删缓存  ← 清理 t4 的脏数据

解决的问题: 并发读在"删"和"更新 DB"之间发生,把旧值写回缓存。


策略B:先更新 DB → 删缓存 → 延迟再删

复制代码
t1: 请求A 更新 DB(新值)
t2: 请求B 查缓存 miss,读到新值  ← DB 已经是最新的,直接命中新值
t3: 请求A 删缓存
t4: 延迟 500ms 再删缓存  ← 兜底,防止 t5 回填

解决的问题: 并发读在"更新 DB"之后发生,如果缓存里还有旧值被命中,回填时用新值覆盖即可。但实际上策略 B 里请求 B 读到的就是新值,所以这个策略的"价值"主要体现在:

  • t1-t3 之间如果请求 B 读到了旧缓存值并回填,t5 的第二次删除兜住
  • 某种程度上是冗余的,因为策略 A 里的第一次"删"才是关键

哪个更好?

策略 A(删 → 更新 DB → 延迟删) 策略 B(更新 DB → 删 → 延迟删)
第一次删/写的时机 先删缓存 先更新 DB
并发读期间读到 旧值(但会被延迟删清掉) 新值(因为 DB 已更新)
复杂性 多一次远程 DB 读 更简单,DB 最新就行
实用性 经典方案,解决明确 简化版,依赖"更新 DB 后读到的就是新值"

策略 A 的问题是:并发读在"删缓存"和"更新 DB"之间发生时,读到旧值并回填,需要延迟删来兜底。

策略 B 实际上更简单------只要 DB 更新了,后续的 Cache Aside 读本身就是新值。延迟双删的核心价值在于"先删缓存"这个动作阻断了并发读把旧值写回缓存的路径。


结论

策略 B 在某些场景下是有效的,但策略A 才是延迟双删的标准写法,因为它真正解决了"删和更新之间"的窗口问题。你在看的资料如果是策略 B,可能是在简化实现------但要理解清楚它的前提假设(DB 已更新,后续读自然拿到新值)。

相关推荐
SL_staff29 分钟前
低代码选型避坑指南:为什么‘能拖拽’不等于‘能交付’?——基于JVS八大引擎的四维交付能力评估框架
java·低代码·spring cloud
李福春1 小时前
技术思考问题6:技术演讲该晒成功架构,还是交代失败与取舍?
java·开发语言·架构·computer use·深圳同盟·腾讯云架构师技术同盟·反演思维
用户7771298509121 小时前
equals和==的区别
java
旋律4141 小时前
对封装、继承、多态三个概念理解
java
code2cat1 小时前
【随笔】LLM裁判如何打分:先写评分标准,再用人工案例校准
java·人工智能·llm·agent·评估·langsmith
SL_staff1 小时前
计息规则不再等IT:JVS-Rules函数计算器在金融计息场景的技术实践
java·git·全栈
古法老登瞎折腾1 小时前
大数据智能运维实战(二):准备一个可复现的运维实验环境
java·大数据·运维·spring ai·mcp
梅菲塔亚1 小时前
博客_Redis入门到实战
数据库·redis·缓存