标准答案

  1. 读流程是先读缓存;命中则返回;未命中时读取数据库或事实来源,再把可缓存的结果按 TTL 回填。
  2. 写流程通常先提交数据库事务,再删除或失效对应缓存,让下一次读从数据库获取新值并回填,而不是在多个位置同步写同一份业务对象。
  3. 对确认不存在的对象可以短暂缓存空值,防止大量不存在的 ID 穿透到数据库;空值必须有较短过期时间,并且要区分“确实不存在”“暂时查失败”和“无权限访问”。
  4. 缓存回填和删除失败需要观测与补偿,例如重试失效、消息通知或后台校对;不能把一次网络调用成功当作缓存一致性的保证。

题目解析

Cache Aside 的优点是应用能按业务决定哪些数据可缓存、何时失效。代价是应用必须处理并发回填、删除失败、TTL 抖动和热点重建,不能只写两行 get/set。

永久缓存空值会把临时错误、延迟创建的数据或错误权限判断固化下来。空值缓存是保护数据库的手段,不是数据状态的永久记录。

代码示例

写入后删除缓存的关键是让数据库提交先完成,并把缓存失效失败纳入重试和告警。

Text
读取:cache.get(key) -> 未命中 -> db.query(id) -> cache.set(key, value, ttl)
写入:db.transaction(update) -> cache.delete(key) -> 失败时记录并异步重试

常见误区

  • 把数据库查不到、数据库超时和无权限都写成同一个永久空值。
  • 在数据库更新前先删除缓存,更新失败后让后续读频繁回源或误以为数据不存在。
  • 回填时不加 TTL 抖动,导致同一批 Key 同时失效。

作者信息