先固定一个判断顺序:用带唯一标记的请求逐层比对响应,而不是反复刷新同一入口。多层缓存(浏览器、CDN、反向代理、应用缓存、对象缓存)各自可能保留不同时间的副本,收录检查看到的“未收录”或“内容不符”往往只是某一层返回了旧版本。定位的目标是找出第一层开始出现差异的位置,再决定清哪一层、是否改缓存键或调整回源策略。
场景一:同一个 URL 在不同网络、不同地区、不同请求头下返回不同正文。常见原因是 CDN 按地域或设备类型分片缓存,而回源逻辑又根据 UA 或 Cookie 输出不同模板。场景二:同一批内容被多个 URL 暴露(带参数、带尾斜杠、大小写变体),各 URL 各自缓存,导致收录检查时抓到的样本互相矛盾。
两种场景的取舍不同。场景一优先做“逐层剥离”:从浏览器直连应用、绕过 CDN,再逐层加回,确认差异最先在哪一层出现。场景二优先做“归一”:确定规范 URL,把其余变体做 301 或 canonical,再逐层检查各变体是否还残留旧缓存。前者代价是排查链路长、需要能绕过各层的访问手段;后者代价是改动 URL 结构,可能影响已有外链和缓存命中率。
如果差异只在特定 UA、Cookie、语言头或 IP 段出现,说明缓存键没有覆盖这些维度,或某一层按这些维度分片。此时不应先清缓存,而应先确认缓存键规则:哪些头参与键计算,哪些头被忽略。忽略的头如果影响输出,就会稳定复现“同一 URL 两个版本”。
如果差异与请求头无关、随时间随机出现,更可能是回源竞争或缓存过期时间不一致。检查各层 TTL 设置:CDN 边缘、中间代理、应用层、对象缓存是否设了不同过期时间。TTL 不一致时,旧副本会在一段时间内持续被部分请求命中。
实施动作:给页面加一个可观测的唯一标记,例如响应头里输出生成时间戳和缓存层标识,或正文里放一个仅在特定条件下出现的注释。用同一 URL 连续请求多次,记录每次命中的层与时间戳。结果会直接决定下一步:若时间戳在某一层之后不再更新,问题在该层;若时间戳每次不同但正文仍旧,问题在回源或对象缓存读取逻辑。
从最靠近源站的一层开始向上验证,顺序通常是:应用直出、反向代理、CDN 边缘、浏览器。每层用相同请求参数,只改变目标地址或 Host,保持路径与查询串不变。对比响应头中的缓存状态字段、正文关键片段和生成时间。
例外:如果站点对未登录用户和登录用户输出不同内容,而缓存层不区分登录态,逐层验证时用匿名请求和带 Cookie 请求分别测,否则会把正常的差异化输出误判为缓存不一致。另一个例外是灰度发布期间,不同节点部署不同版本,此时差异来自发布策略而非缓存配置,应先确认发布状态再排查缓存。
假设某文章页在 CDN 边缘返回的正文里带有“版本 A”,而应用直出已是“版本 B”。给响应头加 X-Generated-At 后连续请求十次:应用直出十次都是新时间戳且正文为 B;经过反向代理后五次新、五次旧;经过 CDN 后全部为旧。这说明分歧最先出现在反向代理层,且该层可能有两台实例缓存状态不一致。下一步应检查反向代理各实例的缓存键与清除广播是否同步,而不是直接刷新 CDN。
这个例子的数字只用于说明比较方法:新时间戳与旧正文同时出现,比单纯看“是否收录”更能指出问题层。若十次请求全部返回同一旧时间戳,则更可能是该层缓存未过期且清除未生效;若时间戳持续更新而正文不变,则更可能是回源拿到了旧数据。
清除某一层后,不要只看一次请求就结束。用同一 URL 在不同网络出口、不同请求头组合下各请求数次,确认返回的正文与生成时间一致。然后把该 URL 加入站点地图或内部抓取队列,观察后续抓取样本是否与当前版本一致。站点地图不保证收录,robots.txt 的抓取限制也不等于可靠的索引移除,这两点会影响你对“是否已一致”的判断,不能把抓取量变化单独当作处理正确的证据。
如果一致性恢复但收录状态没有立即变化,合理解释包括抓取队列延迟、抓取预算分配、页面本身质量信号不足,以及抓取方对更新频率的判断。此时应继续观察抓取日志和样本,而不是反复修改缓存配置。只有当逐层验证再次出现版本分歧时,才回到前面的定位步骤。