八股答得顺不算会,把缓存更新的时序走一遍 缓存题答出「先更新数据库再删除缓存」还没解释方案的边界。把读请求和写请求交错排一遍看看旧值会不会重新回到缓存才知道自己背的是一个操作顺序还是一项有条件的保证。先把讨论缩小数据库是数据来源缓存保存副本读请求命中缓存就返回未命中则查数据库并回填写请求提交数据库后删除对应缓存。这里只讨论一个键和两个并发请求不引入具体产品、复制延迟或跨区域问题。写下每一步别跳过读请求假设缓存恰好为空。读请求先查到数据库里的旧值却还没回填。此时写请求把数据库更新为新值并提交随后执行缓存删除。读请求最后才把刚才读到的旧值写进缓存。顺序完全遵守了「先更新数据库再删除缓存」结果仍然出现旧副本。问题来自读与回填之间隔着一段时间而写请求的删除发生在这段时间里。删除当时可能确实成功只是后来又有旧数据被放了回来。这个反例不需要证明现实里一定经常发生也不能拿来宣布方案毫无价值。它只证明在刚才允许的交错顺序下操作顺序本身不足以排除旧值回填。如果你要给出更强结论就要补充能够排除这条时序的约束。先说清业务允许旧多久展示信息允许短暂落后与库存扣减是否能接受旧状态讨论目标可能不同。先问读到旧值会导致什么后果旧状态是否会自行消失是否有绕过缓存核实结果的路径再讨论一致性要求。过期时间可以限制缓存条目的存活但不能让缓存每次返回的内容都等于当前数据库。读到旧值、旧值重新回填、缓存过期后重新读取是几件不同的事。把过期说成「保证一致」就需要解释保证的是哪种一致以及在什么时间范围内成立。读请求是否可以绕开缓存也有成本。不能一边说缓存承担主要读取一边在关键步骤默认所有请求都会再查数据库却不说明这些请求占哪一部分、为什么要这样区分。每加一种措施继续找新的缝隙如果说稍后再删一次要问等待多久以及删除失败时如何发现。固定等待不能自动覆盖所有慢请求第二次删除也有执行失败的可能。它可以是降低某些风险的措施不应被说成在任意延迟条件下都正确。如果引入版本信息也要说明版本来自哪里、比较和写入是否有原子性。先比较版本再分别执行覆盖中间仍然可能插入别的请求。给数据加一个版本字段并不等于所有参与方都已经按版本规则执行。如果提出串行化某类操作就继续问串行化的范围、失败恢复和吞吐代价。面试不是禁止复杂方案而是每多一个机制都需要知道它挡住哪条路径又留下什么条件。被追问时可以当场修正结论比如你开始说「这样不会有旧值」后来走出反例就明确改成「这个顺序降低了部分更新问题但在未命中回填的并发场景下仍有窗口」。然后围绕业务容忍度继续选措施不必硬把反例解释成不可能发生。能修正前提是技术讨论的一部分。真正麻烦的是换了假设却不承认前面允许请求任意延迟后面又用「正常请求很快」排除慢请求。两段话用了不同模型听起来顺逻辑却接不上。练习基础题时可以给每个结论补三句讨论的系统模型是什么哪条时序可能推翻它我愿意付出什么代价收紧保证。并不是每道题都要画复杂图只要把容易被略过的间隔暴露出来。当一个回答能预测反例、承认边界还能说明业务为什么接受剩余风险它才从记忆题变成了一次设计判断。你回答缓存题时最容易漏掉的是写请求的失败还是读请求延迟回填的那一段