内容改完、後台点了發布,前台看着還是舊样子;或者反過来,缓存過期设得太短,每隔几分钟就有一批請求打回源站,带宽和資料库连接跟着起波動。這两類現象看起来相反,根子都在同一件事上:缓存策略没理清。
先分清三层缓存各由谁管
- 浏览器本地缓存:由响應头里的 Cache-Control、Expires 决定,用戶自己或清理工具能清掉,站点很难强制失效。
- CDN 邊缘节点缓存:由 CDN 的缓存規則和缓存键决定,刷新按钮作用于這一层。
- 源站與應用层缓存:頁面缓存、對象缓存、OPcache、反向代理缓存,通常由运维配置和程序逻辑控制。
排查时先確認問题出在哪一层,不然容易出現「刷了 CDN 還是舊的」「清了浏览器還是舊的」這種来回折腾。
几個值得警觉的信号
- 同一個 URL 在不同地区、不同網絡下拿到的内容版本不一致。
- 後台顯示已發布,前台、接口、搜尋预览三處看到的内容對不上。
- 源站带宽曲线呈現規律性尖峰,間隔與缓存時間接近。
- 带查询參數的 URL 命中率明顯低于不带參數的版本。
- 登入後的頁面偶尔出現別人的信息,或未登入也能看到登入態内容。
排查顺序建议
- 用命令行或浏览器開發者工具看响應头,重点看 Age、Cache-Control、ETag、Last-Modified 以及 CDN 自己加的命中标识。
- 換节点、換地区、換设备各訪問一次,確認是全局問题還是局部节点問题。
- 看 CDN 後台的缓存命中率與回源率,判断是缓存没生效,還是反而缓存過久。
- 检查缓存键規則:是否忽略查询參數、是否按 Cookie 或請求头区分,是否把無意义參數也算進键里。
- 检查源站是否给動態頁面配了過長的缓存時間,或者把登入態頁面当公共资源缓存。
- 確認刷新操作的范围:單條 URL 刷新、目錄刷新還是全站刷新,是否覆盖了带參數的版本。
常见配置誤区
- HTML 文档设了很長的 max-age,结果每次更新都要等用戶缓存自然過期。
- 缓存键里混入追踪參數,同一篇内容在邊缘节点存了十几份副本。
- Vary 头設定不当,導致本该复用的缓存被拆散,或者该区分的没区分。
- 301、302 跳轉被長時間缓存,改完跳轉目标後舊規則還在生效。
- 刷新只處理了主 URL,带參數、带斜杠變体的地址仍指向舊内容。
建议把「改内容、發布、刷新、驗證」寫成一個固定清單,每次更新照着走一遍,比事後猜哪里没生效要省時間。
驗證环节別省
刷新之後至少做三件事:用無痕窗口訪問主 URL,用带參數的地址再訪問一次,再挑一個遠端节点確認。如果站点有接口或小工具,也顺手拉一次,避免頁面更新了、資料接口還是舊缓存。
回源压力同样要盯
缓存時間不是越短越安全。對更新不频繁的静態资源,可以给較長缓存並配合文件名版本号;對经常變動的列表頁和首頁,可以用較短的邊缘缓存加主動刷新。真正的目标不是「永遠最新」,而是更新能被及时看到、回源請求又不會把源站压垮。
把三层缓存的分工、缓存键規則和刷新流程记在一份文档里,值班的人換了一茬也能照着查,站点运营的稳定性往往就体現在這些看起来不起眼的配置上。