页面更新了,访客看到的还是三天前的版本;日志里蜘蛛抓到的 HTML 里,还挂着已经下线的活动入口。这类问题往往不是程序写错了,而是 CDN 缓存和源站之间没对齐。缓存本身是好事,它让站点扛得住流量,也让蜘蛛的抓取更快,但它需要一套明确的刷新规则,否则旧副本会一直在边缘节点上待着。
先分清缓存链路上有哪几层
很多“刷新没生效”的争论,其实是在讨论不同的层:
- 浏览器缓存:由 Cache-Control、Expires、ETag 控制,影响的是回访访客。
- CDN 边缘节点缓存:按 URL、查询串、请求头(如 Accept-Encoding、Cookie)区分副本。
- 源站或反向代理缓存:Nginx、Varnish、应用自身的页面缓存,可能各存一份。
- 静态资源版本:CSS、JS、图片常常单独走一套策略,和 HTML 不同步。
自查时先确认“看到旧内容”具体卡在哪一层。可以看响应头里的缓存状态和 Age 字段,对比命中与否、副本已存在多久,再决定是推刷新还是改配置。
几个容易踩的坑
缓存键里带了不该带的东西
如果缓存键包含会话 ID 或随机参数,命中率会掉到接近零;反过来,如果缓存键忽略了对内容有影响的参数,访客可能拿到别的版本。筛选参数、分页参数、语言参数,要明确哪些参与缓存键,哪些直接忽略。
忽略了 Vary 声明
同一 URL 对移动端和桌面端返回不同 HTML 时,需要正确的 Vary 声明,否则先到的那份会被发给所有人。验证方式很简单:用不同 User-Agent 连续请求几次,看返回的 HTML 是否一致。
长缓存配了短变更
把静态资源 TTL 设成一年是常规做法,前提是文件名带哈希。如果文件名不变又设了长 TTL,改动就只能靠手动刷新,很容易漏掉一两个文件。
刷新策略怎么定
- 发布即刷:正文、标题、价格、库存这类页面,发布流程里带上刷新动作。
- 失效后主动预热:刷新完主动请求一次,别让第一位访客承担回源压力。
- 路径级刷新:栏目页、列表页用目录刷新,比逐条提交 URL 更省事。
- 留下刷新记录:谁在什么时候刷了哪些地址,出问题时能对账。
一份可执行的自查清单
- 抽查十个近期更新过的 URL,看缓存状态和 Age 是否合理。
- 确认缓存键里的参数都有实际作用,没有混进会话标识。
- 检查移动端与桌面端返回的 HTML 是否被正确区分。
- 核对静态资源是否带版本号或哈希,长 TTL 是否与之一致。
- 确认 404、410、301 这类响应不会被长期缓存。
- 确认登录态、后台、购物车等个性化页面不进入公共缓存。
- 确认发布流程里有刷新步骤,有明确负责人和回滚预案。
提示:缓存不是越短越安全。TTL 调得太短,回源压力上升,蜘蛛集中抓取时反而更容易超时。先观察真实命中率和回源量,再决定要不要动这个值。
和蜘蛛的关系
蜘蛛抓到的 HTML 同样来自缓存层。如果栏目页被缓存了很久,新发布的文章可能在列表里迟迟不出现,也就少了一个被发现的入口。给列表页设置比详情页更短的 TTL,通常是比较稳妥的做法。同时也要清楚,刷新缓存只保证蜘蛛拿到的是最新版本,至于什么时候来抓,仍由搜索引擎自己决定。