先判断差异发生在哪一层,再决定是统一缓存键还是缩短某一层的缓存时间。多层缓存出现版本不一致,常见于浏览器、CDN、反向代理和应用内缓存各自保存了不同时间点的响应。定位时不要先清空全部缓存,而是固定一个URL,逐层对比响应头与内容指纹,找到第一个返回旧版本的层级,再针对该层调整缓存键或失效策略。
这两种做法都能减少版本漂移,但代价不同。统一缓存键适合内容版本由URL参数或文件指纹明确区分的情况,例如静态资源带哈希、接口带版本号。此时把各层缓存键对齐到同一维度,可以让同一请求在所有层命中同一份内容,代价是需要改动CDN或反向代理的缓存键配置,并确认查询参数不会被意外丢弃。
缩短缓存时间适合版本切换频繁、但无法保证所有层使用同一缓存键的场景,例如页面HTML中嵌入了动态片段,或移动端与桌面端共用同一URL。把CDN和反向代理的TTL调短,可以让旧版本更快过期,代价是回源请求增加,源站压力上升,页面加载速度优化在缓存命中率下降时可能反而变差。选择依据是:能否稳定地让每一层用同一个键区分版本。能,就统一缓存键;不能,就缩短TTL并接受回源成本。
假设一个页面在浏览器中看到旧版价格,但源站返回的是新版。可以按以下顺序取证据:
Age、Cache-Control、ETag或Last-Modified。Vary头是否覆盖了影响内容的请求头,以及失效通知是否真正到达该层。这个动作的结果会直接决定下一步:如果差异只出现在浏览器层,优先检查本地缓存和Vary;如果差异出现在CDN层,优先检查缓存键和刷新API是否覆盖了该URL;如果各层哈希一致但页面仍显示旧内容,则问题可能不在缓存,而在前端渲染或接口返回。
假设某站点把HTML缓存在CDN 600秒,反向代理缓存300秒,应用内缓存120秒。某次发布后,部分用户看到旧版导航。逐层比对发现CDN层哈希仍是旧版,反向代理和源站已是新版。此时CDN的Age约为420秒,说明它还没过期。若选择统一缓存键,需要让CDN缓存键包含发布版本参数,并在发布时改变该参数;若选择缩短TTL,则把CDN的600秒降到60秒,但回源量会上升。两种选择都成立,区别在于发布频率和源站承受能力。这个例子只用于说明比较方法,不代表任何真实站点数据。
请求量或抓取量归零不能单独证明缓存处理正确。它也可能是监控采样变化、流量本身下降或请求被其他层拦截。同样,某一层返回旧版本,不一定意味着该层缓存失效失败,还可能是上游在写入时就把旧版本传了下来。
另外,Cache-Control: no-cache并不等于不缓存,它通常表示使用前需要向源站验证;no-store才是要求不存储。若把两者混用,多层缓存的行为会不一致。对于带Vary的响应,还要确认各层是否都按同一组请求头区分版本,否则同一URL可能因Accept-Encoding或User-Agent不同而返回不同内容。
当一致性要求很高、且无法保证所有层同步失效时,更稳妥的做法是让版本信息进入URL,而不是依赖各层同时刷新。这样即使某一层仍持有旧响应,新URL也会绕过它,代价是旧URL需要保留一段时间或做重定向。