60 秒回答模板

缓存和数据库一致性通常先讲 Cache Aside:读请求先查缓存,未命中再查数据库并回填;写请求先更新数据库,再删除缓存,让下一次读重新加载新值。相比先删缓存再更新数据库,这个顺序更不容易让并发读把旧值写回缓存。但它仍然可能遇到删除缓存失败、主从延迟、读写并发和业务执行超时,所以要配 TTL、删除重试、延迟双删、消息队列、binlog 订阅补偿、版本号或分布式锁。最后要说明一致性级别:大多数缓存场景追求最终一致;强一致业务要减少旁路缓存,或把写入、失效和读路径放进更严格的事务和校验机制里。

考点 缓存更新策略
难度 后端高频系统题
回答目标 讲清取舍和补偿

深入解析

01

先给出主流读写模型

Cache Aside 的核心是应用自己维护缓存:读时 cache miss 再查 DB 并回填;写时以 DB 为准,提交成功后删除缓存,避免缓存长期保留旧值。

02

解释为什么常删缓存而不是改缓存

删除缓存让下一次读基于数据库重建,逻辑简单,也避免复杂对象组装、部分字段更新和并发覆盖。直接更新缓存只有在数据构造简单且写路径可控时才更合适。

03

把并发时序讲清楚

先删缓存再改 DB 的风险是:缓存刚被删除,并发读查到旧 DB 值并回填,随后写请求才提交新 DB 值,旧缓存会停留到过期。先改 DB 再删缓存通常把这个窗口缩小。

04

删除失败要有补偿闭环

更新 DB 成功但删除缓存失败时,会出现旧缓存。常见兜底是较短 TTL、同步重试、异步重试队列、订阅 binlog 失效缓存,以及对失败任务的告警和人工修复。

05

一致性强度由业务决定

商品详情、用户资料通常能接受短暂最终一致;余额、库存扣减、权限变更的错误成本更高,需要版本校验、事务边界、写串行化或直接读主库,不能只靠普通缓存策略。

06

热点和击穿要单独治理

一致性方案还要防止缓存失效后大量请求打到数据库。热点 key 可以用互斥重建、逻辑过期、随机 TTL、预热和限流,避免一致性处理引发可用性问题。

易错点

  • 说“同时更新缓存和数据库就一致”,没有讨论两边任一失败和并发覆盖。
  • 把延迟双删当成万能方案,不说明它依赖延迟估计且仍需补偿。
  • 只讲更新顺序,不讲删除失败后的重试、TTL、binlog 或告警闭环。
  • 把所有业务都套最终一致,忽略余额、权限、库存等强一致边界。

面试官追问

为什么通常推荐先更新数据库再删除缓存?

因为先删缓存会让并发读有机会把数据库旧值重新写回缓存。先更新数据库再删除缓存也不是完美,但旧值窗口通常更小,且更容易靠重试和 TTL 收敛。

延迟双删解决什么问题?

它试图覆盖写请求期间并发读回填旧缓存的窗口:写前删一次,写后等待一小段时间再删一次。但延迟时间不可靠,仍要配合 TTL、重试和监控。

binlog 订阅补偿有什么价值?

它把数据库变更作为事实来源,异步消费变更事件来删除或更新缓存。适合补偿应用删除失败,也能让多服务共享同一套缓存失效逻辑。

什么时候不能依赖普通缓存最终一致?

当错误成本高、不可短暂读旧值时,例如余额、权限、库存扣减。此时要提高读写一致性,使用事务、版本校验、串行化写入或直接绕开缓存。