缓存是站点运营里最容易被忽略、又最容易出问题的一环。配好了,它能把服务器压力降下来、让页面打开更快;配错了,蜘蛛和用户看到的可能是几周前的旧内容,甚至是一个早就修好的报错页。
缓存本身不改变抓取规则,但它决定了你在什么时候看到什么版本。当一个页面已经修复、已经更新、已经下架,而缓存层还在往外发旧副本时,排查就会变得非常别扭——后台明明是对的,线上却是错的。
缓存最常出问题的几个位置
- CDN 边缘缓存:把 HTML 文档当成静态资源做长缓存,max-age 设成七天甚至一个月,内容改了边缘节点还不知道。
- 反向代理与网关缓存:整页缓存下来,却没有按 Cookie 或登录态区分,登录用户可能看到游客版本,甚至看到别人的页面。
- 应用层缓存:片段缓存、对象缓存过期时间太长,栏目列表和推荐位长期不刷新。
- 浏览器缓存:静态资源没问题,但 HTML 也设了长缓存,用户不强制刷新就看不到更新。
逐项自查清单
1. HTML 文档是否被当静态资源长缓存
图片、CSS、JS 用带版本号的长缓存是好事,但 HTML 文档通常不该这么做。如果响应头里对文档设了很长的缓存时间,内容更新后,边缘节点和浏览器都会继续用旧副本。文档类地址更适合较短的缓存时间配合协商缓存,或者交给 CDN 的刷新接口统一控制。
2. 错误状态是否被缓存
比缓存旧内容更麻烦的是缓存错误。404、500、503 只要带上可缓存的响应头,就会被节点存下来。后台已经修好,外面看到的还是报错页。至少要保证 5xx 不落缓存,回源异常时也不要把结果写进缓存。
3. Vary 与 UA 区分是否到位
同一个地址对不同设备可能返回不同的 HTML。如果缓存键只看 URL,移动端用户可能拿到桌面版,反过来也一样。检查 Vary 头是否包含必要维度,或者干脆用不同地址、子域区分移动版本。
4. 登录态与个性化内容
带 Set-Cookie 的响应、包含用户个人信息的页面,应该标记为私有或不做缓存。把它们缓存到公共节点上,轻则显示错乱,重则泄露信息。
5. 带参数地址的缓存键
追踪参数、排序参数、会话参数会制造大量近似地址。如果缓存键把这些都算进去,节点空间被稀释;如果不算,又可能把不同内容混在一起。对无关参数做规范化,是缓存治理和 URL 治理可以一起做的事。
6. 改版与下线后的清理流程
内容改版、栏目合并、页面下架之后,缓存不会自动知道。要有一个明确的刷新动作:按地址提交刷新、按目录批量清理,必要时改文件名或加版本参数。少了这一步,下线页面可能长期对外可见。
怎么快速排查
- 用命令行工具请求同一个地址两次,观察响应头里的 Age 或缓存命中标记是否在变化。
- 换一个 User-Agent 再请求一次,比较返回的 HTML 是否一致。
- 故意请求一个不存在的地址,连续两次,看第二次是不是直接返回缓存的 404。
- 对比源站和 CDN 返回的响应头,确认缓存策略是不是在某一层被改写。
- 内容更新后立刻访问一次,确认看到的是新版本,而不是节点上的旧副本。
几个容易踩的坑
- 只测首页。首页往往有单独策略,栏目页和详情页才是问题集中区。
- 只看浏览器。浏览器有本地缓存,带一个随机参数请求一次,才能看到节点的真实状态。
- 把刷新当常规手段。频繁全量刷新会让缓存失去意义,回源压力反而更大。
- 把缓存和收录混为一谈。缓存放的是副本,不替你做收录决定,但它决定了蜘蛛当场抓到的是哪一版。
缓存的目标是让正确的版本更快地到达用户和蜘蛛,而不是让某一个版本永远停留。定期花十分钟检查一次缓存策略,比起事后追查线上为什么还是旧的,要省事得多。