缓存是提升訪問速度的常規手段,但它同时也是一层看不见的中間层。訪客和蜘蛛請求同一個地址时,拿到的可能是缓存里的舊副本,而不是服務器上刚更新的内容。發布完更新再去检查,發現頁面上還是上一版,多半就是卡在了這里。
缓存一般出現在哪几個环节
一次請求從浏览器到源站,中間可能经過好几层缓存,每一层的失效規則並不一样,排查时需要分別看。
浏览器本地缓存
由响應头中的 Cache-Control、Expires、ETag、Last-Modified 等字段控制。有效期设得過長,老訪客可能長時間看到舊頁面;设得過短,或者每次都回源校驗,性能收益又會打折。對经常更新的栏目頁和首頁,通常更适合短缓存加校驗;對图片、字体、文件名带版本号的静態资源,長缓存也没有太大問题。
CDN 與反向代理缓存
這一层在源站之前,很多站点預設開啟,但配置項往往没有人認真看。需要留意的是:哪些路径被缓存、缓存時間多長、回源时带不带查询參數、更新後是主動刷新還是等它自然過期。有些站点内容已经改了,CDN 上還挂着几小时前的版本,蜘蛛来抓的时候自然只能拿到舊的。
服務端頁面缓存與對象缓存
不少 CMS 會把渲染好的頁面存成静態文件,或者把查询结果放進内存缓存。内容更新後如果没有触發對應的清除動作,前端看起来一切正常,實际輸出的還是缓存内容。這類問题的特点是:後台顯示已發布,前台就是不變化。
自查时可以按這個顺序過一遍
- 用無痕窗口和正常窗口分別打開同一個頁面,對比内容是否一致,判断是不是浏览器缓存造成的差异。
- 打開開發者工具的 Network 面板,看關键頁面的响應头里缓存相關字段是怎么寫的,重点看 Cache-Control 和 Age。
- 用命令行工具直接請求源站 IP,再請求域名,两次结果對比,看差异是否来自 CDN 层。
- 在後台更新一篇文章,记錄時間,然後分別在几分钟、半小时、几小时後检查頁面,观察它多久才真正刷新。
- 检查静態资源的文件名是否带版本号或哈希值,如果没带又设了長缓存,改图改样式後容易出現新舊混用。
- 確認 CDN 或缓存服務是否提供刷新入口,以及刷新是否覆盖目錄和子路径。
几個容易忽略的情况
第一類是带查询參數的地址。有些缓存策略預設不缓存带參數的 URL,導致同一篇内容有两套响應行為;反過来,也有些配置忽略參數差异,把不同篩選结果当成同一個頁面缓存起来,出現内容張冠李戴。
第二類是移動端與桌面端。如果两端共用同一個地址、靠 UA 判断輸出,而缓存层没有把 UA 纳入区分條件,就可能出現一端拿到另一端的版本。
第三類是登入態與匿名態。用戶登入後看到的頁面被缓存下来,後續匿名訪客也可能看到带有個人信息的版本,這既是体驗問题,也涉及安全。
缓存本身不是問题,問题在于没人知道它缓存了什么、缓存了多久、什么时候會失效。
内容更新和改版时的處理顺序
- 先在源站確認新内容已经正确輸出,再考虑刷新缓存。
- 清除该頁面涉及的服務端頁面缓存對象缓存。
- 刷新 CDN 上對應的路径,而不是只刷新首頁。
- 检查栏目頁、聚合頁、列表頁這類會引用该内容的頁面,它們同样可能被缓存。
- 最後再用無痕窗口和直接請求源站的方式各驗證一次。
如果是整站改版或者 URL 结构調整,除了缓存,還要同步確認跳轉規則、站点地图和内部連結都已经指向新地址,避免舊地址被缓存後繼續對外輸出。
把缓存检查放進日常节奏
缓存問题往往不會立刻暴露,等到發現时可能已经持續了一段時間。比較稳妥的做法是把它並入已有的巡检動作:每次栏目更新或模板調整後,固定检查几個代表性頁面;每季度梳理一次缓存規則,確認哪些路径该缓存、哪些不该;把刷新入口和操作步骤寫進内部文档,避免只有一個人知道怎么處理。
缓存配置没有通用答案,和站点規模、更新频率、技術栈都有關系。重点不是把缓存時間調到某個數值,而是让团队清楚每一层缓存的行為,更新之後知道该去哪里让它生效。