定位一致性问题的核心不是先清缓存,而是先固定一个可复现的请求条件,再逐层比对各层返回的实体标识与响应头。如果只有个别URL出现旧版本,通常说明某一层缓存键或失效规则没有覆盖到该URL;如果规模化出现例外,则更可能是多层缓存对同一资源采用了不同的缓存键、变体判断或失效传播路径。先区分这两种情况,才能决定是修单条规则还是重设整条缓存链。
多层缓存(例如CDN边缘节点、反向代理、应用层缓存、对象存储或浏览器缓存)返回不同版本时,最容易误判的是把“我看到的版本”当成“所有请求看到的版本”。要定位一致性问题,第一步是把请求条件固定下来:同一个URL、同一组请求头、同一出口IP或同一区域节点、同一时间窗口。条件固定后,再逐层请求并记录返回的响应头,重点看能标识实体版本的字段,例如 ETag、Last-Modified、Age、Cache-Control、Vary 以及回源标记。
如果直接访问源站与经过CDN后拿到的 ETag 不同,问题更可能出在中间层缓存键或缓存内容本身;如果 ETag 相同但展示内容不同,则要检查是否由前端渲染、压缩变体或内容协商造成。这一步的实际动作是建立一张“层—请求条件—返回标识”的对照记录,它决定下一步是去查缓存键,还是去查失效通知。
当个别样本成立、规模化后出现例外时,通常有两种解释,而且它们指向不同的修复方向。
解释一:缓存键或变体判断不一致。不同层可能把查询参数、请求头、Cookie、设备类型或压缩方式纳入缓存键,也可能不纳入。某一层按带参数的完整URL缓存,另一层忽略参数,就会出现同一页面在不同节点返回不同版本。这种问题的特征是:差异与请求条件强相关,换一个参数、换一个区域或换一种请求头,返回版本就变化。
解释二:失效传播不完整。内容更新后,源站已返回新版本,但部分中间层没有收到失效通知,或通知到达顺序不同,导致旧副本继续存活。这种问题的特征是:差异与时间相关,刚更新后新旧版本并存,过一段时间部分节点自行恢复,但个别节点长期不恢复。
两种解释可能同时存在,所以不要只凭一次刷新结果下结论。能区分它们的证据是:把同一URL在多个区域节点、多个请求条件下连续采样,如果差异跟着请求条件走,偏向解释一;如果差异跟着节点和更新时间走,偏向解释二。
可以按下面的顺序取证,每一步的结果都会影响下一步动作。
Vary 配置存在分歧。Age。若只有部分节点返回旧版本,且 Age 明显偏大,偏向失效传播不完整。假设一个场景:某页面更新后,源站返回新内容,但两个边缘节点仍返回旧内容,另外三个节点已更新。此时如果改变查询参数后两个异常节点也返回新内容,更可能是缓存键把参数纳入了判断,而失效通知只覆盖了不带参数的键;如果改变参数后异常节点仍返回旧内容,则更可能是这两个节点的失效通知没有送达或处理失败。这个例子只用于说明比较方法,不代表任何真实节点的行为。
个别URL通过清缓存恢复,不代表整套缓存链已经一致。规模化后出现例外,往往说明规则只覆盖了部分URL模式,或者不同层对“同一资源”的定义不同。此时继续逐个清缓存,只会掩盖规则缺口。更稳妥的动作是:先按URL模式、参数模式、内容类型和更新频率分组,找出例外集中在哪一组;再针对该组检查缓存键、变体头和失效通知的配置是否一致。
需要说明适用条件:如果站点同时使用多种缓存层,且各层由不同团队或不同配置管理,一致性问题的定位成本会明显上升,单靠一次抓取或一次刷新无法证明整条链路已经一致。此时应把“可复现的请求条件”和“逐层返回标识”作为交接材料,而不是只提交一个“页面显示旧内容”的现象描述。
另外,抓取限制、站点地图提交或启用HTTPS都不能替代对缓存一致性的排查:robots.txt的限制不等于可靠的索引移除,站点地图不保证收录,HTTPS也不保证缓存层之间自动一致。定位这类问题时,应以逐层返回的实际标识和可复现条件为准,再决定是修缓存键、修失效传播,还是调整更新流程。