先给结论:不要从“哪个版本更新”入手,而要先确认每个版本分别由哪一层产生。多层缓存下出现不同版本,通常不是某一层坏了,而是各层的键、失效条件和回源路径不一致。能区分原因的证据是同一请求在固定输入下的逐层响应头与内容指纹,而不是刷新几次看结果。
假设一个页面已经更新正文,边缘缓存返回新版本,浏览器也显示新内容。但过一段时间,同一地址又回到旧版本。直觉会认为缓存没清干净,但更常见的情况是:边缘层确实拿到了新版本,而回源时上游某一层仍返回旧内容,边缘层于是把旧内容重新缓存。
这个现象的关键不在于“清了几次”,而在于清除动作作用在哪一层、清除后第一次回源请求命中了什么。如果只清边缘层,不清上游或应用层缓存,旧内容会以新缓存的形式再次出现。
第一种解释是缓存键不一致。不同层可能把主机名、协议、查询参数、Cookie、语言头或设备类型中的一部分纳入键,另一部分忽略。结果是同一 URL 在不同层对应不同缓存对象,更新只影响其中一部分。典型证据是:带与不带某个查询参数时版本不同,或不同 Accept-Language 返回不同正文。
第二种解释是失效传播不一致。各层键相同,但清除指令没有按依赖顺序到达,或者某一层不支持按标签、按路径批量失效,只能等自然过期。典型证据是:手动逐层清除后版本一致,但正常发布流程后不一致;或者清除后短时间内一致,超过某个时间又分叉。
这两种解释可以同时存在,所以不要急着下结论。先固定一个可复现请求,再逐层比对,才能把两者分开。
准备一个固定请求:固定 URL、固定请求头、固定查询参数,不携带随机参数。然后依次直连各层,记录响应头中的缓存状态字段、内容长度和正文指纹。动作与结果的关系如下:
这里要提醒一点:请求量或抓取量归零、日志中某层突然没有记录,都不能单独证明缓存处理正确。它们也可能是流量切换、采样变化、日志延迟或上游限流造成的。判断一致性仍要回到内容指纹和响应头。
假设某站点有浏览器缓存、CDN 边缘缓存和应用层对象缓存三层。发布新版本后,边缘层显示新内容,但十分钟后恢复旧内容。逐层直连发现:边缘层回源时,应用层仍返回旧对象,因为应用层缓存以页面 ID 为键,而发布流程只清除了以路径为键的缓存。这个例子说明,键不一致会让清除动作看似成功、实际漏掉目标对象。
对应的动作是:把应用层缓存的键定义与发布流程的清除目标对齐,再重复同一固定请求。如果此后各层指纹在多个时间点保持一致,才说明定位方向正确;如果仍分叉,再回到失效传播顺序排查。
建议顺序是:先固定请求并记录各层指纹,再判断是键不一致还是失效传播不一致,最后才调整清除策略。适用条件是各层可分别直连或至少可观测响应头;如果无法直连,只能通过带标记的请求头间接区分,结论强度会下降。
另外,robots.txt 的抓取限制不等于可靠的索引移除,站点地图不保证收录,HTTPS 也不保证安全无漏洞或排名。这些问题与缓存版本一致性属于不同层面,排查时不要混在一起。缓存一致后,再单独核查抓取与索引状态,才能避免把展示层问题误判为收录问题。