先看一个判断:如果 CDN、反向代理、应用缓存和浏览器缓存各自返回的页面版本不同,问题通常不在“缓存有没有生效”,而在“哪一层把哪一份内容当成权威副本”。定位顺序应该从响应头里的版本线索开始,而不是先清空所有缓存。清空只能掩盖差异,不能证明哪一层是错的。
多层缓存的一致性排查,第一步是把差异具体化。常见差异有三类:一是 HTML 主体不同,比如 A 层返回旧价格、B 层返回新价格;二是响应头不同,比如 Age、ETag、Cache-Control 不一致;三是同一 URL 在不同节点上分别命中不同缓存键。
可执行的动作是:对同一 URL 连续请求多次,每次记录响应状态、Age、ETag、Last-Modified、X-Cache 一类由链路添加的头,以及正文中一个稳定可比的标记,例如页面模板版本号或一段固定文字。结果会影响下一步:如果差异只出现在正文而头完全一致,问题更可能出在缓存键或回源逻辑;如果头本身就不一致,先查各层配置和缓存键规则。
面对多层缓存不一致,常见的决策不是“全部保留”或“全部清掉”,而是分层处理。
Vary 规则,比反复清缓存更接近根因。三种取舍并不互斥。一个常见组合是:对 HTML 保留短 TTL,对静态资源改写缓存键,对无法观测的中间层临时退出。选择依据是你能否用响应头复现差异,而不是哪一层看起来“更高级”。
一个反直觉现象是:清空 CDN 后差异消失,于是被判定为 CDN 问题。但这不能单独证明 CDN 是根因。差异消失还可能因为源站刚好发布了新版本、某个中间层重启、或缓存键在清空后重新生成。要区分这些解释,需要同时看源站直连响应和经过各层后的响应。
假设一个场景:源站直连返回版本 A,经过反向代理返回版本 A,经过 CDN 返回版本 B。此时可先固定请求头(去掉可能影响 Vary 的字段),再分别请求。如果 CDN 在固定请求头后仍返回 B,而源站和反向代理稳定返回 A,那么 CDN 层的缓存键或回源配置更值得优先核查。如果固定请求头后 CDN 也返回 A,则差异可能来自请求头触发的变体,而不是缓存本身出错。
这个动作的结果直接决定下一步:前者去查 CDN 的缓存键与回源规则,后者去查应用层是否正确声明了 Vary,以及是否存在把用户态写进共享缓存的逻辑。
定位完成后,需要留下可重复的观测方式。建议至少记录三样东西:请求时使用的完整头、各层返回的版本标识、以及差异出现的时间窗口。这样下次再出现“多层返回不同版本”时,可以直接比对,而不是重新猜。
如果站点使用站点地图或 robots.txt 辅助管理抓取,要注意:robots.txt 的抓取限制不等于可靠的索引移除,站点地图也不保证收录。它们不能替代缓存一致性检查。HTTPS 同样不保证内容版本一致,也不保证安全无漏洞或排名。不同搜索引擎对缓存和索引的处理须分别核查,不能把一层的结论直接套到另一层。
最终目标是让每一层都能回答“我返回的是哪个版本、依据是什么”。当这个答案可核对时,保留、改写或退出才有依据,而不是靠反复清缓存维持表面一致。