缓存是站点运营里性價比很高的一項優化:静態资源命中缓存,服務器压力小,訪客打開也快。但缓存一旦配错,問题也很直接——内容早就改了,訪客和蜘蛛拿到的還是几個小时甚至几天前的頁面。等到發現列表頁少了新文章、栏目頁還挂着舊标题,往往已经過了一轮抓取。
缓存自查的目标不是把缓存關掉,而是让每一层缓存都清楚自己该存什么、存多久、什么时候失效。
一、先把缓存分层看清楚
排查之前,先確認站点上有哪几层缓存在起作用。很多“改了不生效”的問题,其實是找错了层。
- 浏览器缓存:由响應头控制,影响回訪訪客看到的版本。
- CDN 或反向代理缓存:位于訪客與源站之間,缓存键决定哪些請求算同一個頁面。
- 應用层頁面缓存:CMS 或框架生成的静態化頁面、片段缓存。
- 對象缓存與查询缓存:資料库、Redis 等,影响資料讀取的新鲜度。
常见的誤判是:後台已经更新,資料库也是新資料,但 CDN 上的 HTML 還没過期,前台看起来就是没變。
二、看响應头,別只看頁面
用 curl -I 或浏览器開發者工具的 Network 面板,逐個確認關键地址的响應头。重点看這几項。
- Cache-Control:max-age 控制浏览器缓存时長,s-maxage 针對共享缓存,no-cache 表示可以存但每次要校驗,no-store 表示完全不存。
- private 與 public:带登入態、购物车、個性化推荐的頁面應标為 private,避免被公共缓存串给其他訪客。
- ETag 與 Last-Modified:协商缓存的基础,缺失时每次訪問都要重新回源。
- Vary:用于区分移動端與桌面端、压缩格式等维度,缺失时容易把一種版本返回给所有设备。
比較稳妥的做法是:HTML 用較短的 max-age 或协商缓存,带内容指纹的 CSS、JS、图片用一年期長缓存。指纹變了地址就變,不用担心舊文件被繼續引用。
三、缓存键與刷新策略最容易出問题
缓存键决定了“什么算同一個頁面”。這里有两個方向相反的坑。
- 缓存键包含太多參數,比如把广告追踪碼、會话 ID 都算進去,命中率极低,等于没有缓存。
- 缓存键忽略必要參數,比如分頁、篩選、語言版本,導致不同頁面互相覆盖。
另外要確認私有内容没有被公共缓存,否則可能出現一位訪客看到另一位訪客信息的尴尬情况。發現後應先把相關路径排除在缓存之外,再排查缓存键規則。
缓存时長不是越短越安全。全站 no-store 會放大源站压力,抓取變慢,反而影响新内容被發現的速度。
四、發布後的刷新流程
内容更新後,只刷新必要的地址就够了,不必全站清缓存。可以按下面的顺序處理。
- 刷新被改動的詳情頁。
- 刷新對應的栏目頁、列表頁等聚合入口。
- 刷新首頁中引用该内容的位置。
- 如需更新 sitemap,刷新 sitemap 地址本身。
- 確認刷新完成後再去看前台版本,避免在回源還没結束时反复刷新。
如果站点更新频繁,可以把刷新動作寫進發布流程:先發布、再刷新關键 URL、最後抽查。這样比事後凭印象找問题更可靠。
五、別忽略回源與容量
缓存失效的瞬間,請求會集中涌向源站。如果源站在這一波回源里响應變慢,訪客和蜘蛛都會感受到。可以關注几個信号:
- 缓存命中率是否稳定,是否在發布後出現明顯下滑。
- 源站带宽與响應時間在回源高峰是否接近上限。
- 缓存刷新是否有节流,避免同一時間大批地址同时失效。
有條件的话,把刷新動作分散開,或利用 stale-while-revalidate 這類策略,让舊版本在後台更新的同时繼續提供服務,减少源站尖峰。
六、一頁自查清單
- 列出站点上的缓存层,確認每层由谁控制。
- 抽查首頁、栏目頁、詳情頁、静態资源的响應头。
- 確認登入態頁面、個性化頁面没有被公共缓存。
- 检查缓存键是否包含分頁、語言、设备等必要维度。
- 確認發布後的刷新范围與执行人。
- 观察刷新後源站的响應時間與缓存命中率變化。
缓存策略没有一套通用答案,它取决于内容更新频率、訪問量和源站承受能力。把上面几項检查做一遍,至少能避免“頁面已经改了,訪客和蜘蛛却還在看舊版本”這類本可避免的問题。