WordPress 缓存四层:object cache、页面缓存、CDN、浏览器怎么分层排查

· wordpress · 阅读 18
摘要

对象缓存、页面缓存、CDN、浏览器四层的失效条件各不相同,附从外往里的排查顺序和清完仍不对的三种原因。

WordPress 本身不算慢,慢和「改了不生效」大多来自叠加在上面的几层缓存。这四层各自的失效条件完全不同,清错一层等于白干。先把边界划清。

一、四层各管什么

层存什么失效条件
对象缓存数据库查询结果(WP_Object_Cache)内容更新时按 group 失效,或手动 flush
页面缓存完整 HTML 输出插件监听 save_post 清对应页,或过期时间到
CDNHTML/静态资源边缘副本主动 purge,或 TTL 到期
浏览器静态资源(按 URL+版本)URL 变化或强刷

这四层的更新时机互相独立,是绝大多数「清了没用」的根因。

二、对象缓存:默认只在单次请求内有效

WordPress 内核自带 WP_Object_Cache,但默认是非持久的——只存在于当前这次 PHP 请求的内存里,请求结束就没了。所以默认状态下它不会造成「改了不生效」,反而能减少同一请求内的重复查询。

真正会「卡住」的是持久化对象缓存:装了 Redis Object Cache、Memcached 这类 drop-in(wp-content/object-cache.php)。此时缓存跨请求存在,内容更新后如果没触发对应 group 的失效,前台就一直读旧值。

// 判断当前是否启用了持久对象缓存
wp_cache_supports('get_multiple'); // 加上外部 drop-in 才有意义
var_dump(file_exists(WP_CONTENT_DIR . '/object-cache.php'));

排查动作:后台或 WP-CLI 执行 wp cache flush,再看是否恢复。恢复了就说明是这一层,接下来要查的是「为什么更新内容没触发失效」——通常是用了直接写库的 SQL,绕过了 save_post 之类的钩子。

三、页面缓存:最常见的错觉来源

WP Rocket、LiteSpeed Cache、W3 Total Cache 这类插件会把整页 HTML 落盘。后台发文后前台还是旧的,九成是这一层。

它们的失效逻辑通常挂在 save_post / transition_post_status 上,只清首页和相关归档页。以下场景容易漏清:

  • 改了侧栏模块或小工具 → 不影响任何文章,没人去清
  • 改了主题选项 → 同上
  • 用 REST API 或脚本直接写库 → 钩子根本没跑
  • 多站点/多域名 → 只清了主域名那份

验证方法是绕开插件:带一个随机查询串访问,或者临时禁用页面缓存插件再刷新。带 ?nocache=1 不一定有用——很多插件只对登录用户或特定参数跳过缓存。

四、CDN 与浏览器:最外层但最好排查

CDN 看的是响应头:cf-cache-status: HIT(Cloudflare)、x-cache: HIT(各类反代)都说明命中了边缘缓存。HTML 被缓存是重灾区——很多配置默认把 .html 也纳入缓存,文章更新后要主动 purge。

浏览器那层主要影响 .css / .js。判断标准很简单:URL 不变、内容变了,浏览器一定用旧的。解法是改版本号,而不是让用户去按 Ctrl+F5:

wp_enqueue_style(
    'my-style',
    get_template_directory_uri() . '/style.css',
    array(),
    filemtime(get_template_directory() . '/style.css')  // 文件改动时间自动当版本
);

用 filemtime() 当版本号,改文件即换 URL,缓存问题自动消失。这一招能消掉一半「我明明改了 CSS」的困惑。

五、按这个顺序查,别乱清

  1. 强刷浏览器(Ctrl+Shift+R),排除第 4 层
  2. 看响应头里有没有 CDN 的 HIT,有就先 purge
  3. 禁用页面缓存插件刷新一次,恢复到哪一层就清楚了
  4. flush 对象缓存(wp cache flush)
  5. 以上都排除,才回头看数据库里数据到底改了没

第 5 条最常被跳过。比如用脚本写 update_post_meta() 时 key 拼错,数据库里根本没有这个 meta,前台当然取不到——这跟缓存一点关系都没有,清一百遍也没用。

六、清完还是不对的三种原因

一、OPcache。PHP 层面的字节码缓存,改 .php 文件后不重启 FPM 或不等 opcache.revalidate_freq 过期,跑的还是旧代码。改插件文件后「完全没变化」优先怀疑它。

二、定时任务没跑。有些缓存清理逻辑挂在 WP-Cron 上,而 WP-Cron 是靠访问触发的。站点流量低、或 DISABLE_WP_CRON 开了却没配系统 cron,任务就永远排队。查 wp cron event list 看有没有堆积的 pending。

三、缓存键里带了用户/设备维度。移动端和桌面端各存一份、登录与未登录各存一份。你清了未登录那份,用管理员身份访问看到的仍是另一份,误以为没清干净。排查时用无痕窗口、退出登录再看。

小结

记住分层的判断顺序比记住工具名有用:浏览器 → CDN → 页面缓存 → 对象缓存 → 数据库,从外往里剥。清完仍不对,就往 OPcache 和 Cron 这两个「不在缓存名单里但效果像缓存」的地方看。