先给有条件的结论:如果同一 URL 在不同请求中返回不同内容版本,且差异出现在 HTML 主体而非仅响应头,优先怀疑“应用层缓存与边缘缓存键不一致”,而不是主机磁盘或数据库。这个结论成立的前提是你已经确认源站本身输出稳定;一旦源站在无缓存直连时也返回多个版本,结论立即失效,问题在应用或数据层,继续查缓存只会浪费时间。
多层缓存通常指应用内缓存(如对象缓存、页面缓存)、反向代理缓存和 CDN 边缘缓存。它们返回不同版本时,现象并不一样:
这三种表现对应的排查入口完全不同。先记录“差异是否与请求头、时间点、来源 IP 相关”,比直接清缓存更有价值。
面对版本不一致,两种做法都成立,但代价不同。
做法一:先清空所有缓存层,再观察是否复现。适用条件是问题刚出现、影响面大、你需要尽快恢复一个可预期状态。代价是清缓存会抹掉证据:原本能通过对比响应头定位的缓存键问题,被一次性清空后可能暂时消失,过一段时间又出现。它适合止血,不适合定位。
做法二:先固定请求条件,逐层比对响应。适用条件是你还能复现,且业务允许带问题运行一段时间。做法是保持 URL、请求头、Cookie、来源一致,分别向边缘、反向代理和源站直连发起请求,记录每次返回的内容摘要和响应头中的缓存标识。代价是耗时,且需要能绕过外层直接访问内层。
如果问题只在部分用户出现、且你无法控制他们的请求头,做法二很难执行,此时做法一更现实,但清完后必须立刻用固定请求复测,否则等于没查。
假设你按上面的思路确认边缘缓存键缺少语言参数,于是给缓存键加上语言维度,版本不一致消失。这看起来是缓存配置问题。但如果源站在高并发下会因后端节点不同而输出不同语言版本,那么加缓存键只是把差异从边缘推到了源站,问题会在流量再次升高时回来。
判断方法很简单:在源站直连、不带任何缓存的情况下,用相同请求连续发起多次,观察返回是否稳定。如果源站本身就返回多个版本,那么无论缓存键怎么设计,一致性都无法保证。此时下一步动作不是继续调缓存,而是检查后端节点配置、会话粘滞或数据同步。
每一步的结论决定下一步:源站稳定才值得继续查缓存键;源站不稳定则缓存配置再正确也无法消除版本差异。这个顺序的价值在于,它不会让你在错误的层反复清缓存。
只写“清了缓存后正常了”无法复查。至少记录:请求的完整 URL、关键请求头、响应中的缓存状态标识、返回内容中用于区分版本的字段,以及每次请求的时间。内容摘要可以用版本号、语言标记或页面中一个稳定字段代替全文,避免记录过多无关数据。
需要提醒的是,抓取量或请求量归零不能单独证明处理正确,它也可能是外层缓存命中率上升、请求被合并或监控口径变化造成的。同样,robots.txt 的抓取限制不等于可靠的索引移除,站点地图也不保证收录。这些现象与缓存版本一致性无关,不应混进同一份判断里。
最后给一个下一步动作:在完成逐层比对后,把“源站是否稳定”作为分叉点。源站稳定,就修正缓存键和 TTL 差异;源站不稳定,就带着相同请求条件的记录去找应用或后端负责人,而不是继续在外层缓存上做调整。