知识卡片
Cache Aside模式为什么要求先写数据源后失效缓存
内容
缓存污染指缓存中的数据和真实数据源不一致,多数由更新姿势不规范造成 (比如更新对象后业务异常回滚,导致缓存是新值、数据库是旧值)。Cache Aside是成本最低的应对模式:读时先查缓存,没有再查数据源并回填;写时 先写数据源,再让缓存失效(而不是更新缓存)。这里有两个容易被忽略但很 关键的细节。顺序必须是”先数据源后缓存”:如果反过来先失效缓存再写数据源, 就会有一段真空期——缓存已经清空、数据源还没改完,此时新的查询请求会 因为缓存未命中直接查到数据源里的旧值,还会把这个旧值重新回填进缓存, 等数据源真正改完后,就变成数据源是新值、缓存却是刚回填的旧值,问题反而 更难排查。动作必须是”失效”而非”更新”:如果选择直接更新缓存,一旦数据源 在更新缓存的过程中又被别的请求修改,就要面对多次赋值应该以哪次为准的 复杂时序问题;而选择让缓存直接失效,无论数据源被改了多少次,下次访问 时都会老老实实回源拿最新值,不会有旧值覆盖新值的风险。Cache Aside并 不能保证在所有极端时序下都绝对一致——如果一个从未被缓存过的数据,恰好 在”查询请求已发出、还未回填缓存”的窗口期被写操作抢先修改,依然可能出现 短暂不一致,但这种情况概率很低,Cache Aside仍是低成本换取相对可靠结果 的主流方案。
参考来源
- 位置:《凤凰架构:构建可靠的大型分布式系统》第4章"透明多级分流系统"
4.6.2节"缓存风险"(源文件:_epub-src对应OEBPS/Text/chapter55.xhtml)
- 结论依据:原文说明Cache Aside要求先写数据源后失效缓存(反过来会导致
真空期读到旧值并回填),以及应失效而非更新缓存(避免多次赋值的复杂
时序问题),并承认该模式在极端窗口期仍可能不一致但概率很低,直接支撑
本卡片结论。
- 原始内容:一是先后顺序是先数据源后缓存……另一点是应当失效缓存,而不是
去尝试更新缓存……Cache Aside模式依然不能保证在一致性上绝对不出问题,
否则就无须设计出Paxos这样复杂的共识算法了。