先给结论:多层缓存下同一URL返回不同版本,通常不是“死链检查工具不准”,而是请求经过的缓存层不同,命中了不同副本。要定位一致性问题,先把“哪个URL、从哪条路径、拿到哪一版”变成可核对的记录,再逐层排除。下面以一个具体页面为对象,给出可执行的处理顺序。
不要一上来就全站跑检查。选一个已经出现版本不一致的URL,记录三项:完整URL(含协议、主机、路径、查询串)、请求时带的请求头(尤其是缓存相关的头)、以及你从哪个网络位置发起请求。同一个URL在不同出口、不同设备上结果不同,往往说明问题出在缓存链路而不是源站内容。
假设一个例子:某页面在办公网打开是旧版,在手机热点打开是新版。这个差异本身不是结论,而是一条线索——它提示两条路径命中了不同缓存。此时应固定同一URL、同一请求头,分别从两条路径各请求若干次,记录每次返回的状态码和响应体中一个稳定特征(例如页面里一个固定文案或版本标记)。
判断一致性,关键不是看页面长得像不像,而是看响应头能不能把请求落到哪一层说清楚。重点看这些字段:
Age:大于0通常表示响应来自缓存,数值可帮助判断副本有多旧。Cache-Control:max-age、s-maxage、no-cache、private直接决定哪一层可以缓存、缓存多久。ETag与Last-Modified:不同副本如果这两个值不同,说明它们对应的源站版本不同。Vary:如果它包含了Accept-Encoding、User-Agent等,说明同一URL会因请求头不同而分出多个缓存键。实际动作:对同一URL连续请求两次,第二次带上与第一次相同的请求头。如果第一次和第二次的ETag不同,或Age没有按预期增长,就说明中间有层在返回不同副本,而不是源站稳定输出同一版本。这个结果会直接决定下一步——是去查缓存键设计,还是去查源站发布流程。
多层缓存常见结构是:浏览器缓存 → CDN/边缘缓存 → 反向代理缓存 → 应用层缓存 → 源站。定位一致性问题的有效顺序是从内往外,而不是从外往内。
这里有一个容易误判的点:抓取量或请求量突然归零,并不能单独证明缓存处理正确。它也可能来自抓取工具被限流、网络中断、或目标层临时不可达。要区分这些解释,需要同时看状态码、响应时间和响应头,而不是只看数量。
版本分歧最常见的两个根因,是缓存键设计不一致和失效规则没覆盖全层。
缓存键方面:如果某一层把Accept-Encoding算进键、另一层不算,同一个URL就会产生压缩版和未压缩版两个副本,检查工具可能把它们当成不同页面。要核对的是各层Vary与键规则是否一致。
失效规则方面:发布新版本后,如果只清了CDN却漏了反向代理,或者只按路径清而没带查询串,旧副本就会继续被命中。此时的动作是:列出所有缓存层,逐层确认失效是按URL、按目录还是按标签触发,并验证失效后Age是否归零、ETag是否更新。
一个可操作的取舍:如果多层缓存由不同团队维护,优先统一缓存键和失效触发条件,而不是在检查工具里加更多忽略规则。忽略规则只会掩盖分歧,不会消除它。反过来,如果分歧只出现在极少数带特定查询串的URL上,且业务上这些URL不要求强一致,那么把检查范围限定在核心URL上、记录已知差异,也是成立的——前提是差异被明确记录,而不是被当成随机波动。
最后一步不是“修好了”,而是把定位过程变成别人能复现的记录。每条记录至少包含:URL、请求头、请求路径、状态码、Age、ETag、版本特征、以及该结果指向哪一层。这样下一个人不必重新猜,也能判断某个现象是缓存副本还是真实内容变更。当同一URL在不同层持续返回不同版本时,先改缓存键或失效规则,再重新分层验证,直到各层对同一请求给出可解释的一致结果。