站点运营里有一類問题很隐蔽:後台明明改完了,图片換了、價格改了、條款更新了,訪客截图發過来却是舊版本。多數时候不是服務器没更新,而是缓存在中間层把舊内容繼續發了出去。缓存本身是好事,它能让頁面更快、让源站压力更小,但如果缺少刷新與驗證机制,它就會變成“看不见的舊版本仓库”。
先弄清缓存落在哪几层
排查之前,先知道一份頁面從源站到訪客浏览器之間會经過哪些环节。不同层級的失效方式不一样,只看其中一层很容易誤判。
- 浏览器缓存:由响應头里的 Cache-Control、Expires、ETag 控制,只影响單個訪客。
- CDN 邊缘节点:内容被複製到各地节点,回源频率由缓存規則决定。
- 反向代理與 Web 服務器缓存:如 Nginx 的 proxy_cache、fastcgi_cache。
- 應用层缓存:頁面缓存、片段缓存、對象缓存,常见于内容管理系統。
- 資料库與查询缓存:结果被暂存,資料更新後未必立刻反映。
同一個“頁面没更新”的現象,可能来自其中任意一层,也可能是几层叠加。
静態资源與 HTML 要区別對待
最常见的配置错誤,是把 HTML 和图片、CSS、JS 用同一套缓存規則。前者内容會變,後者通常靠文件名版本号来区分。
- 带指纹或版本号的静態资源,可以設定很長的缓存時間,更新时換文件名即可。
- HTML 頁面缓存時間不宜過長,或使用协商缓存,让浏览器每次回来問一句。
- 接口返回的資料要單獨评估,尤其是價格、库存、登入狀態相關内容。
- 別對带用戶信息的頁面做公共缓存,否則可能把 A 的信息發给 B。
缓存键設定得越细,命中率越低
缓存键决定了“什么样的請求算同一個頁面”。如果键里包含了多余的參數、Cookie 或设备标识,命中率會骤降,源站压力反而上升;反過来,键里漏掉了影响内容的维度,就會出現串内容的尴尬。
常见做法是:忽略無意义的跟踪參數,保留真正影响輸出的語言、地区、终端類型等维度。改完規則後,用不同參數多請求几次,確認返回内容符合预期。
更新發布时,刷新顺序很重要
一次改動往往涉及多层缓存,顺序错了就會出現“新的 HTML 配舊的 CSS”這類错位情况。
- 先發布源站内容,確認源站直连訪問得到的是新版本。
- 再刷新 CDN 上與本次改動相關的 URL,必要时按目錄或标簽刷新。
- 接着清理應用层與對象缓存,避免頁面模板已经更新、資料仍是舊的。
- 最後處理浏览器端,靠版本号或文件名變更让訪客拿到新资源。
- 發布後對着關键頁面做一轮抽查,而不是只看首頁。
几招快速驗證缓存是否生效
- 用命令行查看响應头,關注 Age、Cache-Control、X-Cache 之類的字段,判断請求是否命中节点。
- 用無痕窗口或換一個網絡环境訪問,排除本地缓存干扰。
- 抓不同地区的节点,或借第三方工具,確認各地返回一致。
- 看訪問日誌里 304 與 200 的比例,比例異常往往說明缓存策略有問题。
- 發布後固定抽查几個高频入口頁,比等到用戶反馈要省事得多。
缓存不是“设完就忘”的功能,它是需要跟着發布流程一起走的一环。把它寫進上线检查清單,比事後逐层排查轻松得多。
把它變成日常习惯
不需要每次發布都全量刷新,但需要有一份明确的規則:哪些内容必须即时生效,哪些可以容忍几分钟延迟;谁负责刷新,刷新後怎么驗證。把這些寫下来,新同事接手时就不會只改文件、不刷缓存。站点运营的很多麻烦,本质上都是流程缺了一小步,而不是技術做不到。