线路观察
正文更新了,图片为什么还是旧的:缓存新鲜度、验证器与边缘失效的边界
同一页面的HTML、图片与脚本是不同缓存对象。判断旧图不能只靠刷新,而要逐个核对对象URL、缓存键、新鲜度、验证器、边缘状态与源站字节,并让清除范围和实际缓存键一致。
维护者把正文和三张图片一起部署。桌面浏览器马上出现新版本,手机却是新正文配旧图;隐私窗口又只旧一张。反复刷新看似在“加大力度”,实际混合了多个对象、多个缓存层和不同请求条件。
真正的问题不是“缓存有没有清掉”,而是哪个请求仍选中了哪个已存响应。HTML、每张图片、样式和脚本都有自己的URL与响应;它们不会因为出现在同一页面,就共享一份新旧状态。
先把页面拆成对象
浏览器取得HTML后,才从标记中发现图片、样式和脚本地址。正文更新说明HTML对象已变化,不说明图片对象也被重新获取。若三张图沿用旧URL,浏览器可以继续复用其中任何一张的已存响应。
排查时先列完整对象清单,不写“首页图片”这种模糊名称。记录HTML URL、三张图片的绝对URL、是否带查询参数、大小、内容类型和你预期的文件摘要。路径大小写也要原样保留。
同一文件在构建目录、源站与正式域名可能有不同字节。先对实际部署输出算摘要,再从正式URL下载并计算摘要;两者不一致时,问题发生在发布或提供阶段,不应先归罪于用户浏览器。
若正式URL直接取得的字节就是旧文件,清浏览器没有意义。若正式无缓存请求已是新文件,而普通浏览器仍显示旧图,才继续检查私有缓存、验证与边缘响应。
缓存键决定“同一个”是什么
RFC 9111说明,缓存键至少由请求方法和目标URI构成。常见缓存主要保存GET响应,因此完整URI通常是最直观的起点。图片A和图片B路径不同,就是两个对象;HTML与图片更不会自动一起更新。
URI相同也未必只有一份副本。内容协商时,响应的Vary可以让某些请求头参与选择。平台还可能把设备类别、Cookie、指定请求头或其他属性加入自定义缓存键。
这解释了一个常见反例:维护者在桌面清除了某个URL,手机仍旧,不一定代表清除传播失败。如果移动端请求条件形成另一个缓存键变体,而清除请求没有覆盖构成键的值,两边本来就在读取不同对象。
查询参数同样不能凭直觉判断。有的配置把完整查询串纳入键,有的忽略它,有的只保留白名单参数。把“?v=2”加到图片后若确实产生新缓存键,能避开旧对象;若平台忽略该参数,它仍可能命中原副本。
所以“地址看起来一样”和“缓存键相同”不是同一命题。诊断记录应保存浏览器实际请求的完整URL与关键请求头,而不是只抄页面上肉眼可见的文件名。
新鲜不代表源站最新
缓存保存响应是为了复用。RFC 9111把可直接复用的响应称为新鲜响应;只要新鲜度条件成立,缓存无需联系源站,就可以把先前内容交给当前请求。
这时源站文件已经替换,也不会自动改变边缘或浏览器对现有副本的年龄判断。旧图仍处于新鲜期,正是缓存按规则工作的结果,不等于传输损坏。
新鲜寿命可能来自Cache-Control的max-age或共享缓存使用的s-maxage,也可能来自Expires或启发式计算。Age显示响应在缓存链中累积的年龄,但它不是文件发布时间,也不是版本号。
看到Age增加,只能说明当前响应经历了缓存年龄计算。Age很小也不保证内容新,因为旧字节可能刚被重新写入缓存;Age为零更不能单独证明请求访问了源站。
浏览器刷新会改变请求方式或缓存指令,但不同浏览器、开发者工具选项和中间缓存的处理并不完全等价。与其把刷新次数当证据,不如保存请求与响应字段。
陈旧以后可能只是验证
副本过了新鲜期,并不等于一定下载完整新文件。缓存可以向上游发送条件请求,用ETag或Last-Modified作为验证器询问已存响应是否仍有效。
如果上游判断内容未改变,可以返回304。缓存随后更新已存响应的部分字段,继续复用原来的实体字节。网络上传输的是验证结果,不是整张图片。
这项机制节省带宽,却要求验证器可靠。若部署替换了图片字节但仍产生相同ETag,或Last-Modified没有反映变更,304会让缓存合理地保留一个对维护者而言“意外”的旧实体。

反方向也要避免误判。收到200和完整文件只说明这次传输了实体,不保证它是你期望的版本。必须用长度、摘要或可识别像素比对实际字节。
强验证器适合确认表示是否逐字节等同;时间型验证器的精度和生成方式可能有限。不要用页面发布日期代替资源响应里的验证器,也不要把304解释成“没有经过服务器”。
浏览器、边缘和源站是不同层
私有缓存通常服务单个用户,浏览器最典型;共享缓存可以服务许多用户,CDN边缘是常见形式。两层都可能保存响应,但控制面和失效方式不同。
边缘控制面完成清除后,不会替每个用户删除本机已经保存的图片。浏览器仍可能在自己的新鲜期内直接复用。反过来,用户清空浏览器缓存也不能删除边缘副本。
源站是第三个观察点。若源站构建目录有新图,但生产服务器仍提供旧图,边缘清除后只会把旧图重新装入缓存。此时连续出现MISS也不能算修复。

分层验证可采用三组请求:普通正式请求、明确绕过本地缓存的对照请求,以及能代表源站输出的受控检查。每组都保存时间、地区、完整URL、响应字段与摘要。
不要为了“直连源站”而跳过TLS、Host或访问控制,导致请求条件与正式流量完全不同。对照的目的在于改变一个变量,而不是创造另一套无法比较的路径。
失效不是删除所有副本的魔法
HTTP标准规定某些成功的不安全请求会使相关已存响应失效,但协议语义不等于某家CDN的全局主动清除控制面。发布写入成功、边缘对象失效、浏览器副本过期是三个事件。
平台官方说明,按单文件URL清除会从各数据中心删除指定资源。之后的新请求获取最新源站版本,并在处理该请求的数据中心重新缓存;后续缓存状态通常先看到MISS。
单文件清除适合已知对象,因为范围小、回源影响可控。需要替换三张图片时,应清楚列出三条完整URL,不能只清HTML并期待它引用的资源被连带删除。
若使用包含请求头、Cookie或其他属性的自定义缓存键,仪表板单文件清除可能无法携带这些值。遇到这种配置时,官方文件要求改用能包含相应键材料的API请求,或选择前缀、标签等覆盖范围更明确的方法。
路径转换也会带来错位。平台文档要求单文件清除使用最终用户看到的未转换URL。拿内部改写后的路径清除,可能没有命中用户请求所对应的对象。
为什么不先清除全部
全站清除能让更大范围的对象失效,却不是零成本按钮。官方建议优先使用单文件清除,因为全站清除后,大量资源的新请求会回源验证或重新获取,重流量站点可能突然增加源站压力。
精确清除与全站清除的区别不只是快慢。前者要求你知道对象和缓存键,适合局部改图;后者适合无法安全枚举范围或发生广泛错误时的紧急处置,但会牺牲缓存命中并扩大验证面。
如果根因是源站仍旧、验证器错误或HTML还引用旧文件名,全站清除只会扩大问题。所有边缘节点重新取回同一旧字节后,维护者可能误以为“清除没有生效”。
清除之后应观察具体资源的首次响应与后续响应。单文件清除后的MISS只证明该边缘位置没有直接复用先前对象;还要验证实体摘要,才能确认取回的是新版本。
版本化URL更适合不可变资源
图片内容变化时改文件名或加入真正参与缓存键的内容版本,可以让新HTML引用一个从未存在于旧键中的对象。旧资源即使继续留在缓存,也不会被新页面请求。
最稳妥的是内容寻址:文件名包含内容摘要的一部分,字节变化便产生新URL。此时可以给图片较长的新鲜期,同时让HTML使用较短策略或验证器,以便及时指向新资源。
版本化URL不是清除的替代品。若错误文件含敏感内容、旧页面仍引用它,或同一版本路径被错误复用,仍需要主动移除和修正引用。
查询参数版本只有在平台确实把参数纳入缓存键时才可靠。相比依赖未记录的参数规则,改变路径或文件名更容易在日志、HTML和网址清单中核对。
不要在每次请求生成随机参数。它会制造大量不可复用对象,降低缓存价值,也让问题难以复现。版本应与内容或发布批次稳定绑定。

建立可复算的响应矩阵
为HTML和每张资源各建一行。列出完整URL、请求时间、地区或网络、状态码、Cache-Control和Age;另一组字段保存ETag、Last-Modified、平台缓存状态、Content-Length与内容摘要。
先在普通窗口复现,再用不复用本地副本的受控请求比较。每组对照固定浏览器、设备与URL,仅替换查询参数、请求头或网络位置中的一项,否则会失去因果线索。
如果普通请求旧、受控请求新,重点查私有缓存和请求条件。如果两者都旧,但源站受控输出新,重点查共享缓存与清除范围。如果源站输出也旧,返回部署产物和发布目标核对。
若某地区新、另一地区旧,应核对两次请求的完整键,再比较边缘状态和实体摘要。不同地区结果可以提示副本差异,却不能由两个样本还原全球分布。
把预期写成可证伪句子,例如“该图片URL在不复用浏览器副本时应返回摘要X,首次边缘状态为MISS,随后可能HIT”。比“现在应该好了”更容易停在明确结论。
怎样收束一次旧图事件
结案至少需要四项证据:生产输出中是新字节;正式HTML引用精确的新资源URL;目标请求条件下返回新摘要;相关缓存策略与未来更新方式已经记录。
若继续沿用同一URL,记录新鲜寿命、验证器生成方式和清除路径。若改用版本化文件名,确认旧HTML、邮件或外部嵌入是否仍需兼容。
公开响应字段只能说明这一次观察到的请求与响应。它不能证明平台每个内部层级如何路由,也不能证明所有地区和所有用户已经同时一致。
一次刷新不构成证据,一次MISS也不构成完整修复。把对象URL、缓存键、新鲜度、验证结果、失效范围和实体摘要连成一条链,才有资格判断旧图留在哪一层。
发布前怎样设计更新策略
资源策略应在出问题前确定。经常变化的HTML需要较短的新鲜期或可靠验证器,不常变化且文件名带内容摘要的图片可以使用较长新鲜期。两者放在同一策略下,往往不是过度回源,就是更新迟滞。
构建流程可以生成一份资产清单,保存逻辑名称、发布文件名、字节数和摘要。HTML生成时只能引用清单里的文件,避免手工替换图片后仍留下旧路径,也能在发布前发现文件漏传。
部署采用原子切换时,HTML与资产应作为同一批次可用。先让HTML引用尚未到达边缘的文件,会短暂出现404;先覆盖同名图片再发布HTML,则可能让旧页面提前看到不相容的新图。内容寻址文件能降低两者互相覆盖的风险。
回滚也要遵守相同边界。若上一版HTML引用的摘要文件仍保留,切回HTML即可恢复;若每次都覆盖同名资源,回滚页面却未回滚图片,便会出现反方向的混合版本。
监测不应只检查首页状态码。至少抓取HTML中实际引用的资源,验证每个URL返回200、内容类型正确且摘要属于当前发布清单。这样能发现正文成功、第二张图漏传这类局部失败。
需要兼容旧链接时,可以暂时保留旧摘要文件,但新HTML必须只引用新清单。旧资源存在不代表缓存未清,关键在于当前文档是否继续请求它。
把协议事实压缩成六个可执行判断:RFC 9111规定新鲜响应可不经验证直接复用,陈旧响应则通常需要验证或满足允许陈旧的条件。缓存键至少包含方法和目标URI,Vary与平台自定义属性还可能产生多个响应变体。
条件请求用ETag或Last-Modified验证副本;304会更新已存响应的字段并继续复用原实体,而不是传回完整文件。单文件清除只删除指定边缘对象,版本化URL则让新HTML请求一个从未存在于旧缓存键中的对象;全站清除范围最大但会增加回源负载。
清除CDN边缘对象不会自动删除浏览器私有缓存,也不能修复源站仍提供旧字节或自定义缓存键未被覆盖的问题。逐项记录HTML与每张资源的完整URL、状态码、Age、ETag、Last-Modified;保存缓存状态和内容摘要,再决定是否清除或更换版本化URL。
资料依据:IETF《RFC 9111: HTTP Caching》,2022;平台缓存文件《Purge by single-file》《Purge everything》《Revalidation》,2026。
资料来源
- IETF:《RFC 9111: HTTP Caching》,发布或更新于 2022-06-01
- Cloudflare:《Purge by single-file》,发布或更新于 2026-07-23
- Cloudflare:《Purge everything》,发布或更新于 2026-04-16