内容發布完就顺手点一下提交入口,是很多人的固定動作。但提交之後蜘蛛真正抓到的,未必是你刚寫好的那一版。中間隔着的 CDN、反向代理、頁面缓存,只要有一层還留着舊副本,蜘蛛拿到的就是舊内容,而且它並不知道這是舊的。
缓存可能存在于哪几层
排查之前先有個大致的地图,不然容易只刷新一层就以為搞定了。
- 浏览器缓存:主要影响回訪用戶,對蜘蛛的影响相對小,但會影响你自己判断頁面是否真的更新了。
- CDN 邊缘节点:最容易出問题的一层。不同节点的缓存時間不完全一致,同一 URL 在一處是新版、另一處是舊版,並不罕见。
- 反向代理與頁面缓存:Nginx 的 fastcgi_cache、Varnish、各類整頁缓存插件都属于這一层。
- 應用层對象缓存:缓存的是資料库查询结果或頁面片段,外壳是新的,正文却還是舊的。
缓存没刷新时,蜘蛛實际會看到什么
這些現象往往不會立刻暴露,容易和別的問题混在一起。
- 标题和描述仍是修改前的版本,搜尋结果里長期顯示舊标题。
- 列表頁和首頁没有出現刚發布的文章,蜘蛛顺着列表走也找不到新入口。
- 已经下线或刪除的頁面仍然返回 200 和完整内容,相当于舊頁面一直還在。
- 比較麻烦的一種:新頁面正式上线前被訪問過,404 被缓存下来,蜘蛛来的时候拿到的還是 404。
几個值得關注的响應头
用命令行工具或浏览器開發者工具看一眼响應头,通常比反复猜测快得多。
- Cache-Control:重点看 max-age 和 s-maxage。s-maxage 针對的是共享缓存,也就是 CDN 那一层,很多人只調了 max-age 却漏掉了它。
- stale-while-revalidate:允许先返回舊内容、再去後台更新。對用戶是友好的,但蜘蛛拿到的可能正是那份舊内容。
- Age:表示這份副本在缓存里已经放了多久。Age 很大而内容没變,說明缓存命中;Age 很小却仍返回舊内容,反而說明刷新没生效。
- Vary:設定不当时,移動端和桌面端可能互相拿到對方缓存的版本。
内容更新後可以固定下来的動作
- 確認這次改動影响的 URL 范围:只有詳情頁,還是栏目頁、首頁、站点地图都要一起動。
- 按层刷新:先應用层缓存,再 CDN,必要时刷新目錄而不只是單個 URL。
- 用绕過缓存的請求驗證一次,確認返回的确實是新内容。
- 如果站点地图或订阅源有更新,顺手也刷新一遍,它們本身就是蜘蛛的發現入口。
- 把這一步寫進發布流程,而不是依赖某個人正好记得。
和搜尋蜘蛛之間的關系
需要说清楚的是,蜘蛛拿到舊版本並不等于出错。抓取本来就是异步的,它這次看到舊内容,下次再来還能看到新的。真正的影响是時間差:新内容被發現得晚,舊内容在索引里留得久,删掉的頁面可能繼續被訪問到。
另一個常见誤区是“為了保險,全站设成 no-store”。這样做确實不會缓存到舊内容,但每次訪問都要回源,服務器压力上来之後,蜘蛛的抓取速度反而可能下降。更稳妥的做法是区分對待:列表頁、首頁這類更新频繁的頁面缓存時間短一些,詳情頁可以長一些,但前提是刷新通道是通的。
缓存本身不是問题,失控的缓存才是。你要的不是“永遠不缓存”,而是“更新之後能立刻換掉”。
一份可以定期過一遍的清單
- 随机抽几個最近更新過的頁面,看响應头里的 Age 和實际内容版本是否一致。
- 確認 404、410 這類狀態碼没有被長時間缓存。
- 確認 301 跳轉的缓存時間没有设得過長,改版調整时才好轉弯。
- 確認發布、修改、刪除三種操作都有對應的刷新動作。
- 记錄一次刷新到生效大致需要多久,心里有個數。
這些事情單獨看都不复杂,麻烦的是分散在不同人的手里。把它寫進發布清單,比事後反复追問“為什么蜘蛛還没看到新頁面”要省事得多。