• 请不要在回答技术问题时复制粘贴 AI 生成的内容
CharlieLiu
V2EX  ›  程序员

记一次网站缓存排查:改完内容清了所有缓存,访客还是看到旧版

  •  1
     
  •   CharlieLiu · Sep 29 · 1300 views

    先说结论,可能不少人已经知道了:WordPress 挂了对象缓存和 CDN 之后,清缓存的顺序要从最里层往外——先 Redis ,再服务器整页缓存( Nginx FastCGI ),最后 CDN 。顺序反了,清了也白清。

    我前阵子反复遇到一个场景:后台改完文章提示成功,前台打开还是旧内容。第一反应清缓存,一层两层三层全清一遍,还是旧的。加个 ?v=123 马上就新了,去掉参数又变回旧的。

    折腾了一段时间才把链路想明白。

    三层缓存各自的性格:

    1. CDN:缓存整页 HTML ,按 URL 做键,有自己的 TTL
    2. Nginx FastCGI cache:也是整页 HTML ,按 URL 做键,落在磁盘上
    3. Redis 对象缓存:缓存的是数据库查询结果。注意,它默认没有 TTL ,写进去就一直躺着,直到被显式删掉

    坑就藏在第 3 条里:

    • 你改了文章,数据库里已经是新内容
    • Redis 里还是旧数据
    • 这个时候有访客或者爬虫进来
    • PHP 从 Redis 捞到旧数据,渲染出一份"全新的旧页面",丢给 Nginx 缓存了起来
    • 你事后去清缓存,就算把 Redis 和 Nginx 都清了,上面那份旧页面可能早被 CDN 吃进去继续对外发了

    也就是说:清理动作的时机和顺序不对,反而会把旧内容"固化"一层。

    为什么必须从里往外清:任何两步清理之间都有窗口期,窗口期进来的请求,会拿"还没清的那层"的旧数据,把"刚清完的那层"重新填满。先清外层的话,内层的旧数据一秒钟就把外层又填回去了。

    判断卡在哪一层,我一般两个动作就够:

    1. 看响应头。curl -sI 页面地址,看 cf-cache-status / x-cache 之类的字段,确认这次命中的是哪一层
    2. 加随机参数对比。带参数的 URL 不会命中按 URL 缓存的层,所以:带参数是新的、不带是旧的,说明卡在 Nginx 或 CDN ;两个都旧,就是对象缓存或数据层;两个都新,那只是浏览器在骗你

    再补一个容易走偏的点:如果响应头显示 MISS 、页面却还是旧的,那缓存是清白的,大概率是写入根本没成功。这个我踩过——折腾半天缓存,最后发现是保存流程没走完。

    后来我把流程固定成这个顺序,基本没再翻过车:

    先确认写入成功(直接读库里的字段,别信后台的提示)→ 清 Redis → 清 Nginx (能用按路径的定向清除就别整目录删)→ 清 CDN → 从源站直连抓一次比对,顺便预热 → 最后走公网再抓一次看响应头(可能还是 HIT ,正常,TTL 没到而已)。

    还有两个边角:

    • 浏览器缓存能骗过所有服务端清理,无痕窗口也要新开一个才算干净
    • 有的 CDN 对静态资源会忽略查询字符串,?ver= 改版本号没用,只能改文件名或者整站清

    详细的命令和这套顺序我整理成了文档放在自己站上(软件和运维的笔记站,就这一条自己链接,介意的可以略过): https://gkmix.com/wordpress-cache-configuration/

    最后想请教一个点:对象缓存这块,你们是每次改完手动清,还是挂了自动失效的钩子?我目前还是手动的,想看看有没有更省心的做法。

    bobox
        1
    bobox  
       Sep 29
    redis 缓存去掉就行了。没必要。
    abigeater
        2
    abigeater  
       Sep 29
    太多层了 看起来 nginx/redis 选一层去掉就好了
    CharlieLiu
        3
    CharlieLiu  
    OP
       Sep 29
    两位说得都对,能少一层是一层。我这套留着 Redis 主要是替 MySQL 扛动态请求和后台的查询。真要精简,一般也是先摘它——全页缓存对访客的收益更直接。这篇写给已经堆了几层、在收拾顺序的人。还没堆的话,就按你们说的来。
    UEFI
        4
    UEFI  
    PRO
       Sep 29
    > 你改了文章,数据库里已经是新内容
    > Redis 里还是旧数据

    这个感觉不太对啊,是缓存插件的问题吗?修改文章不应该主动刷新缓存吗?

    另外,确实感觉缓存太多层了,我一般是只留 CDN 缓存
    doveyoung
        5
    doveyoung  
       Sep 30   ❤️ 1
    我真求求了,不要再发 AI 生成的文章了,你自己读着不难受吗
    shuijingwanwqyy
        6
    shuijingwanwqyy  
       Sep 30
    我的博客也是基于 WordPress 的。我也是 3 层缓存,不过缓存是基于 W3TC 实现的,用了对象缓存与页面缓存,然后 CDN ,大陆用于为主的使用 EdgeOne ,海外用户为主的使用 Cloudflare 。我感觉当更新一篇文章时,不是应该同步更新对象缓存与页面缓存么?至于 CDN ,我一般是不更新的,让其自然过期后,再回源更新了。
    页面缓存我不是基于 Nginx 了。
    shuijingwanwqyy
        7
    shuijingwanwqyy  
       Sep 30
    我做 3 层缓存,主要是服务器 2 核心 4GB 的,有时候爬虫流量会导致告警了。所以不得不用了 3 层,以避免流量直接打在 PHP 上了。
    CharlieLiu
        8
    CharlieLiu  
    OP
       Sep 30
    @UEFI 你说得对。WordPress 正常保存文章时,核心会主动清掉这条对象缓存——正常路径上不该出现"库改了、Redis 还是旧的"。我写的那一节,前提其实是另一种情况:绕过 WordPress API 的写入(直接改库、SQL 直连、phpMyAdmin ),那条路径不触发清理钩子。这个前提我没写出来,回头补上。
    CharlieLiu
        9
    CharlieLiu  
    OP
       Sep 30
    @doveyoung 建议收下了,回头看。让 AI 润色了下,读起来像一直机器在总结。
    CharlieLiu
        10
    CharlieLiu  
    OP
       Sep 30
    @shuijingwanwqyy 你留三层的理由( 2 核 4GB + 爬虫流量告警)比能少一层是一层更站得住,资源不够的时候,先让流量别打到 PHP 上,优先级是对的。
    对象缓存在正常保存时确实会跟着失效,真正不会自动失效的是页面缓存那一层(按 URL 存整页的,Nginx FastCGI 或 W3TC 的 page cache 都算)。所以最需要手动干预的是它,CDN 让它自然过期反而是省事的做法,你这套已经把那步成本最高的( CDN 推送)省掉了。
    doveyoung
        11
    doveyoung  
       Sep 30
    @CharlieLiu #9 你这句不还是 AI 生成吗?包括 #10

    人家认认真真回复你,你连打几个字都不愿意?你是 AI 的 UI 吗?

    我错了各位 GPT 大人,等智械危机的时候一定要饶我一命。
    tiaod
        12
    tiaod  
       Sep 30
    哥们如果你这个回复不是 AI 写的,那你真的 AI 用的走火入魔了,被 AI 入侵思维了
    shuijingwanwqyy
        13
    shuijingwanwqyy  
       Sep 30
    @CharlieLiu W3TC 的页面缓存在文章更新时,也会自动失效的。我倒是遇见过缓存不更新的一种情况了,就是 WordPress 中使用了多个独立域名了。比如说后台用 admin 、前台用 www 、en 。这种情况下,如果多个插件之间相互干扰,是有可能缓存不自动更新了,需要自己开发 MU 插件修复了。
    shuijingwanwqyy
        14
    shuijingwanwqyy  
       Sep 30
    @CharlieLiu 我不太明白,这些帖子还有评论,还要怎么让 AI 润色了。要不是看见其他的评论,还不是很明确,竟然是 AI 生成了。只是感觉有时候读起来有点别扭了。哈哈。
    About   ·   Help   ·   Advertise   ·   Blog   ·   API   ·   FAQ   ·   Privacy   ·   Solana   ·   2313 Online   Highest 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 40ms · UTC 03:20 · PVG 11:20 · LAX 20:20 · JFK 23:20
    ♥ Do have faith in what you're doing.