← 每日面试题 学习看板

如何保证本地缓存的一致性?

面试题/02架构设计题/06本地缓存/如何保证本地缓存的一致性?.md

完整讲解(权威版)

最后更新:2026-11-01 · 基于第 1 次作答

L1 · 30 秒速记

结论:缓存一致性本质是"数据更新后缓存未同步"的中间态,方案按一致性强度递进——TTL 兜底最终一致 → Cache Aside 删缓存 → 延迟双删 → binlog 订阅删除 → 读后回填。 关键词:Cache Aside · 延迟双删 · binlog 订阅 边界:强一致需写库后失效并控制并发读写顺序;"删缓存"比"更新缓存"更稳。

L2 · 核心讲解

核心考点定位:考察缓存一致性问题的根因(更新顺序 + 并发读写竞态)与多级方案取舍;面试官想看到"先分析不一致怎么产生,再给方案",而非只背"先更库再删缓存"。

机制链(≥3 环):

  1. 写库 + 缓存更新 → 两个独立动作非原子 → 任一顺序都可能产生不一致中间态 → 本质是"写库与写缓存的竞态"。
  2. Cache Aside:写库成功后删缓存 → 下次读未命中再回填 → 比更新缓存少写放大,且避免覆盖新值。
  3. 删缓存后、回填前被并发读写入旧值 → 用延迟双删:删缓存 → 等写库完成后再隔一个延迟(如 500ms)删一次 → 旧值回填在第二次删除时被清掉。
  4. 复杂/强依赖场景 → 订阅 binlog(Canal)监听 DB 变更 → 解析后触发缓存删除/更新 → 解耦、可靠、可重试。

证据锚点:

对比与权衡:

方案一致性复杂度实时性适用
TTL 兜底最终一致低有延迟可容忍不一致
Cache Aside 删缓存最终一致低高常规
延迟双删最终一致(更强)中高高并发写
binlog 订阅最终一致(可靠)高高复杂/强依赖
读后回填接近强一致中高写少读多

常见误区:

  1. 错误:"更新缓存比删除缓存好" → 正确:写后删缓存更稳,避免并发写覆盖新值 → 为什么:更新缓存要保证顺序,删除让下次读重建。
  2. 错误:"先删缓存再更库" → 正确:先更库再删缓存(或延迟双删),先删后更库会让并发读回填旧值 → 为什么:删后更库前被读回填旧值,且旧值可能长期存在。
  3. 错误:"加 TTL 就绝对一致" → 正确:TTL 只保证最终一致,TTL 窗口内仍不一致 → 为什么:过期前读到的是旧值。
  4. 错误:"延迟双删的延迟随便设" → 正确:延迟要大于写库耗时 + 读回填耗时,否则第二次删除覆盖不了回填 → 为什么:窗口估算错误导致旧值残留。

适用边界:

延伸追问(≥3)

  1. 为什么"先更库再删缓存"仍可能不一致?
  1. 延迟双删的第二次删除失败怎么办?
  1. binlog 订阅(Canal)方案的成本?
  1. 缓存击穿/穿透/雪崩与一致性什么关系?

面试者参考回答

【结论】 缓存一致性本质是写库与写缓存的竞态,方案按一致性强度递进:TTL 兜底 → Cache Aside 删缓存 → 延迟双删 → binlog 订阅;写侧用"删缓存"比"更新缓存"更稳。

【三点】

第一,根因与兜底:写库与缓存更新非原子,先接受最终一致,TTL 保证最终收敛。

第二,删除策略:写库后删缓存(Cache Aside),下次读重建;高并发下用延迟双删(删 → 等写库+读回填窗口 → 再删)覆盖旧值回填。

第三,可靠一致:复杂场景订阅 binlog(Canal)监听变更触发删除,解耦可重试;要求强一致则读后回填 + 控制读写顺序。

【边界】 强一致缓存需串行化读写,代价高;TTL/删除只给最终一致;binlog 有解析延迟与运维成本,需权衡后选型;延迟双删的延迟窗口要覆盖"写库 + 读回填"耗时,估算偏小会导致旧值残留。

面试记录 2026-11-01(第 1 次)

题目:如何保证本地缓存的一致性?

难度:medium

标签:cache/consistency, local-cache, general/knowledge, difficulty/medium

评分:⭐⭐⭐⭐☆(4/5)

我的回答

缓存一致性基本都不会是强一致性的,核心是数据更新后缓存没有更新产生的不一致中间状态;

要解决这个问题,最简单的就是给缓存设置过期时间,过期时间到了有访问,自然会重新获取,这样中间会有不一致的过程,但是最终会一致的,主要用在可以接受不一致的场景;

另外就是当数据库更新后,删除缓存,等待下次调用将缓存设置上,这样如果有访问的很快就能设置上缓存;但是高并发下可能会出现,删除过程中新的访问写入了旧的数据导致缓存不一致,这块延伸的处理是延迟双删,启一个子任务过一会再删除缓存;

另外复杂度要求高的,可以通过订阅数据库binlog日志,检测数据库变动,触发式的进行缓存删除;

以及当数据库变更后,直接从主线程读取数据直接设置缓存,来保证强一致

点评

评分:⭐⭐⭐⭐☆(4/5)

优点:结构化——先点明"基本非强一致、不一致中间态";TTL 兜底最终一致;Cache Aside 更新后删缓存;高并发竞态→延迟双删;复杂场景→订阅 binlog 触发删除;读后回填强一致。层次清晰。

不足:没区分 Cache Aside / Write Through / Write Back 三种模式;延迟双删的"第二次删除失败"重试未提;"先删缓存后更新库 vs 先更新库后删缓存"的取舍未展开。

补充:补①Cache Aside / Write Through / Write Back 区分;②延迟双删第二次删除失败的重试;③缓存击穿/穿透/雪崩(读侧)与一致性(写侧)的分层。

完整讲解见上方「完整讲解(权威版)」