为什么缓存失效比缓存命中更难
缓存系统里,命中率是最容易被展示的指标;真正决定系统可靠性的,却是失效。
三个时间同时存在
一份缓存数据至少有三个时间:写入时间、过期时间、最后一次被验证的时间。问题在于,业务数据的变化时间往往没有这么整齐。用户改了昵称,帖子被删除,权限被收回,这些事件不会自动沿着所有缓存副本传播。
一个常见的实现是“更新数据库后删除缓存”。听起来简单,但删除失败、并发读写和主从延迟都会让旧值重新回到缓存。于是系统看起来大多数时候是对的,只在少数时刻给出最糟糕的答案。
async function readPost(id) { const cached = await cache.get(`post:${id}`); if (cached) return cached; const post = await db.posts.find(id); await cache.set(`post:${id}`, post, { ttl: 60 }); return post;}上面这段代码的命中逻辑没有问题,问题在于它没有回答:数据库更新后,谁负责让这个 key 消失?
失效是一种协议
成熟的做法不是追求“永不失效”,而是把失效当成协议来设计:版本号、单调递增的 revision、变更日志、短 TTL 加后台校验,都是在让不同副本对“旧”达成一致。
缓存命中让系统变快,缓存失效让系统可信。后者通常更值得花时间。


评论
登录后可以评论,也可以回复某条评论。
还没有评论
说说你的看法,或者指出文中没有说清的地方。