计算机科学有句名言,说是只有两件难事:命名和缓存失效。前面几篇讲了缓存怎么命中,这一篇讲它的反面——缓存怎么失效。这是缓存阶段最难的部分,也是线上事故的高发区。
为什么缓存失效难
缓存失效难,难在「一致性」。缓存的目的是「不问源站就用旧副本」,但源站更新了,旧副本就是错的。你要在「尽量用缓存」和「保证内容最新」之间找平衡——这两者天然冲突。
用得越久的缓存越快,但越可能过期;频繁失效的缓存保证新鲜,但失去了缓存的意义。所有缓存失效策略,都是在这两端之间取舍。
失效的三种正路
让缓存失效,有三种靠谱的方式:
第一种:文件指纹(内容寻址)
给资源内容算个哈希,作为文件名的一部分:app.a3f9.js。内容一变,哈希变,文件名变。旧文件名对应的旧资源自然没人请求(HTML 里引用的是新文件名),旧缓存慢慢淘汰。
这是最优雅的方案:不用主动失效,靠文件名变化自然失效。webpack/vite 默认这么干。配合长 max-age 和 immutable,浏览器能放心缓存一年——因为内容变了文件名也变,不存在「用了旧副本」。
代价是 HTML 必须用短缓存或 no-cache,因为它引用的 JS/CSS 文件名要能及时更新。HTML 是入口,错了全错。
第二种:短 TTL + 协商缓存
对于不能用文件指纹的资源(HTML、API 响应),用短 TTL(如 max-age=0 或 no-cache),让它们每次都走协商缓存问源站。这样内容更新了,下次请求 ETag 对不上,自然拿到新版本。
代价是每次都要发请求(虽然是 304,省了 body 但还是有一次往返)。适合「不能缓存太久,但也不能完全不缓存」的场景。
第三种:CDN 主动刷新
CDN 提供主动失效 API(或控制台按钮),资源更新后主动通知 CDN 清掉旧缓存。这是 CDN 层特有的能力——浏览器缓存没法主动刷新(除非用户自己清)。
代价是:刷新有传播延迟(全球节点要逐个清),而且如果刷新太频繁,等于没用缓存。通常配合版本化路径(/v2/api)来减少刷新需求。
stale-while-revalidate:用旧的换性能
RFC 5861 引入了一个聪明的指令:stale-while-revalidate。
Cache-Control: max-age=600, stale-while-revalidate=60 的意思是:资源缓存 600 秒;过期后,在接下来的 60 秒内,可以先用旧副本响应,同时后台异步向源站刷新。
这个机制解决了「过期瞬间」的性能尖峰:正常情况下,资源过期那一刻,下一个请求要等源站验证(协商缓存有往返)。有了 stale-while-revalidate,那个请求直接拿到旧副本(快),后台刷新后后续请求拿到新副本。用户感知不到刷新,但内容最终会更新。
代价是:用户可能短暂看到旧内容(最多 stale-while-revalidate 那么久)。对于「最终一致即可」的内容(新闻列表、商品页),这个代价可以接受;对于「必须立即最新」的内容(余额、库存),不能用。
缓存的常见陷阱
实战中,缓存失效踩的坑通常不是策略选错,而是边界没考虑到:
- POST 响应默认不缓存。很多人以为所有响应都能缓存,其实 GET/HEAD 才默认可缓存。POST 要显式配
Cache-Control才缓存。 - 查询参数影响缓存。
/api?ts=123和/api?ts=124是两个不同的缓存键。加时间戳是「绕过缓存」的技巧,但如果你不小心在链接里带了随机参数,缓存就全废了。 - 301 永久重定向会被强缓存。一个 301 响应如果带了长 max-age,浏览器会一直缓存这个重定向。万一你 301 错了,用户设备上的缓存改不掉(除非手动清或等过期)。所以 301 要慎用,考虑用 302/307 测试稳定后再改 301。
- Service Worker 是另一层缓存,它能拦截请求,行为和 HTTP 缓存不同,排查「为什么缓存不更新」时别忘了这一层。
取舍与边界
缓存失效没有银弹,关键是匹配场景。下面这张决策树是快速选型的路径:
- 静态资源:文件指纹 + 长 max-age + immutable。零失效需求。
- 半静态内容(偶尔更新):短 TTL + 协商缓存,或 stale-while-revalidate。
- 实时内容(余额、库存):no-store,不缓存。
- CDN 层:能主动刷新就用,减少对 TTL 的依赖。
收束:缓存是收益与一致性的权衡
整个缓存阶段到此收束。强缓存、协商缓存、Vary、多层缓存、失效策略——这五块构成了 HTTP 缓存的完整图景。它们的共同主题是:在性能(少请求)和一致性(内容最新)之间找平衡。
下一篇进内容与编码阶段——缓存解决了「要不要重传」,接下来讲传输的内容本身:内容协商、压缩、分块、范围请求。
关于十三Tech
我是十三,All in AI Agent 方向的架构师,专注 AI 工程实践。
我相信 AI 是程序员的最佳搭档,也希望帮助每一位开发者更好地驾驭 AI。
如果你想继续跟完这套「图解 HTTP」,欢迎关注公众号 「十三Tech」。后续会按 URL 与报文、连接与传输、缓存与协商、安全与边界、HTTP/2 与 HTTP/3 这条线更新。

