缓存是提升访问速度的常规手段,但它同时也是一层看不见的中间层。访客和蜘蛛请求同一个地址时,拿到的可能是缓存里的旧副本,而不是服务器上刚更新的内容。发布完更新再去检查,发现页面上还是上一版,多半就是卡在了这里。
缓存一般出现在哪几个环节
一次请求从浏览器到源站,中间可能经过好几层缓存,每一层的失效规则并不一样,排查时需要分别看。
浏览器本地缓存
由响应头中的 Cache-Control、Expires、ETag、Last-Modified 等字段控制。有效期设得过长,老访客可能长时间看到旧页面;设得过短,或者每次都回源校验,性能收益又会打折。对经常更新的栏目页和首页,通常更适合短缓存加校验;对图片、字体、文件名带版本号的静态资源,长缓存也没有太大问题。
CDN 与反向代理缓存
这一层在源站之前,很多站点默认开启,但配置项往往没有人认真看。需要留意的是:哪些路径被缓存、缓存时间多长、回源时带不带查询参数、更新后是主动刷新还是等它自然过期。有些站点内容已经改了,CDN 上还挂着几小时前的版本,蜘蛛来抓的时候自然只能拿到旧的。
服务端页面缓存与对象缓存
不少 CMS 会把渲染好的页面存成静态文件,或者把查询结果放进内存缓存。内容更新后如果没有触发对应的清除动作,前端看起来一切正常,实际输出的还是缓存内容。这类问题的特点是:后台显示已发布,前台就是不变化。
自查时可以按这个顺序过一遍
- 用无痕窗口和正常窗口分别打开同一个页面,对比内容是否一致,判断是不是浏览器缓存造成的差异。
- 打开开发者工具的 Network 面板,看关键页面的响应头里缓存相关字段是怎么写的,重点看 Cache-Control 和 Age。
- 用命令行工具直接请求源站 IP,再请求域名,两次结果对比,看差异是否来自 CDN 层。
- 在后台更新一篇文章,记录时间,然后分别在几分钟、半小时、几小时后检查页面,观察它多久才真正刷新。
- 检查静态资源的文件名是否带版本号或哈希值,如果没带又设了长缓存,改图改样式后容易出现新旧混用。
- 确认 CDN 或缓存服务是否提供刷新入口,以及刷新是否覆盖目录和子路径。
几个容易忽略的情况
第一类是带查询参数的地址。有些缓存策略默认不缓存带参数的 URL,导致同一篇内容有两套响应行为;反过来,也有些配置忽略参数差异,把不同筛选结果当成同一个页面缓存起来,出现内容张冠李戴。
第二类是移动端与桌面端。如果两端共用同一个地址、靠 UA 判断输出,而缓存层没有把 UA 纳入区分条件,就可能出现一端拿到另一端的版本。
第三类是登录态与匿名态。用户登录后看到的页面被缓存下来,后续匿名访客也可能看到带有个人信息的版本,这既是体验问题,也涉及安全。
缓存本身不是问题,问题在于没人知道它缓存了什么、缓存了多久、什么时候会失效。
内容更新和改版时的处理顺序
- 先在源站确认新内容已经正确输出,再考虑刷新缓存。
- 清除该页面涉及的服务端页面缓存对象缓存。
- 刷新 CDN 上对应的路径,而不是只刷新首页。
- 检查栏目页、聚合页、列表页这类会引用该内容的页面,它们同样可能被缓存。
- 最后再用无痕窗口和直接请求源站的方式各验证一次。
如果是整站改版或者 URL 结构调整,除了缓存,还要同步确认跳转规则、站点地图和内部链接都已经指向新地址,避免旧地址被缓存后继续对外输出。
把缓存检查放进日常节奏
缓存问题往往不会立刻暴露,等到发现时可能已经持续了一段时间。比较稳妥的做法是把它并入已有的巡检动作:每次栏目更新或模板调整后,固定检查几个代表性页面;每季度梳理一次缓存规则,确认哪些路径该缓存、哪些不该;把刷新入口和操作步骤写进内部文档,避免只有一个人知道怎么处理。
缓存配置没有通用答案,和站点规模、更新频率、技术栈都有关系。重点不是把缓存时间调到某个数值,而是让团队清楚每一层缓存的行为,更新之后知道该去哪里让它生效。