缓存失效怎么选:TTL、版本与事件
舒心读
18
卷中目录
缓存的难点通常不在“把值放进去”,而在“什么时候不再相信这个值”。设计之前,先回答两个问题:数据多久变化一次?读者最多能接受多久的旧值?
本篇目标: 为一个公开书目列表选择失效策略,并处理缓存过期瞬间的回源压力。

TTL 是时间上限,不是实时保证
给缓存设置有效期,能够限制旧值长期存在。有效期越短,回源通常越频繁;越长,越需要接受相应的数据延迟。不要只凭感觉选择一个数字,可以先观察更新频率和读请求量,再确定初始范围。
还需要分清数据 TTL 与权限有效期。某份列表允许短暂过时,不代表失效的授权也可以继续沿用同样时长。
版本键适合成批变化
公开书目有明确的发布版本时,可以把版本号放进缓存键。新版本发布后,读请求切换到新键,旧键再按时间清理。
public-books:v12:page1
public-books:v13:page1
版本要来自可信的发布流程。若版本先更新、实际数据还未就绪,新键也可能缓存到不完整结果。需要约定版本与数据可见性的顺序。
事件失效需要考虑消息丢失
数据修改后发送失效事件,可以缩短旧值持续时间,但要考虑重复、延迟和丢失。通常会保留一个兜底 TTL,而不把整个正确性寄托在“消息一定即时送达”上。
对于敏感或强一致的数据,缓存策略必须服从业务约束。某些读取宁可直接核对当前状态,也不应该在失效时继续返回旧值。
防止同一时刻集体回源
大量键同时到期,可能把压力集中到后端。可以给过期时间增加小范围随机偏移,并合并同一键上的并发回源请求。单进程合并只能影响本进程,多实例场景还需要考虑共享协调或整体并发限制。
空结果也可以短暂缓存,降低反复查询不存在对象的开销,但有效期通常应更谨慎,避免新数据出现后仍长时间查不到。
上线前用“同时过期、事件丢失、更新到一半、回源失败”四种情况演练。记录命中率之外,也关注旧值年龄和回源错误,才能知道缓存是在改善体验,还是把问题暂时藏住。
见字如晤