没有不值得去解决的问题,也没有不值得去学习的技术!

WordPress 多域名架构下 W3 Total Cache 缓存失效:Polylang、Redis 与 admin 子域名的完整排查和修复

WP 博客多语言化实操

查看按语言划分的用户统计,排名前 4 的语言(英语、中文、印尼语、越南语)(如图3)

(1) 博客多语言化决策|为什么我决定花时间做多语言?(附真实发现)

博客多语言插件选型|免费vs付费、服务端vs浏览器端,实测对比+配置教程

(2) 博客多语言插件选型|免费vs付费、服务端vs浏览器端,实测对比+配置教程

附上我翻译完成后的分类效果截图(如图11),中文与英文的分类总数相等

(3) 博客分类翻译实操|695个分类,4小时手动翻译全流程(避坑指南)

最后分别查看中文与英文后台下的标签统计,符合预期。如图17

(4) 博客标签翻译实操|8060个标签,基于 PHP 脚本实现全流程

如图11:最终效果,在前台,语言切换器的显示

(5) 博客菜单翻译实操

如图20对应场景:网站前台效果,顶部语言切换器(中文/英文),点击英文后,网站整体切换为英文版本,文章列表按发布时间倒序排列(与中文文章排序一致),点击任意英文文章,可正常查看,语言切换流畅;同时,英文文章的发布时间、分类、标签与中文原文完全对应,URL路径规范,SEO友好。

(6) WordPress 多语言博客文章翻译实操全记录(Polylang 插件,附避坑指南)

配图说明(如图10):中文、英文分类管理页面截图(分屏对比),标注两个页面的分类总数,演示数量一致/不一致的场景。

(7) WordPress 新增文章分类标签多语言前置翻译流程(Polylang 总数校验+标签脚本复制避坑)

完成后,访问中文系列页 https://你的域名/series/self-hosted-vpn-series/,点击顶部的 English 切换按钮,就能正常跳转到 https://你的域名/en/series/self-hosted-vpn-series-en/ 了。如图13

(8) 告别手动编号:用 PublishPress Series 优雅管理 WordPress 系列文章

WordPress 经典编辑器代码块无损迁移:批量转换 SyntaxHighlighter 短代码为 Gutenberg 区块

(9) WordPress 经典编辑器代码块无损迁移:批量转换 SyntaxHighlighter 短代码为 Gutenberg 区块

点击翻译按钮后,遇到一个弹窗“神秘”闪退问题及解决方法

(10) 点击翻译按钮后,遇到一个弹窗“神秘”闪退问题及解决方法

中文标签出现冗余新增(如图2),数据彻底错乱。

(11) WP 6.9 标签同步脚本在 WP 7.0 失效完整排查与解决实录

重点避坑:仅勾选数据库无法完成数据还原,选中库之后,右侧数据表列表点击全选,囊括库内所有数据表(如图3)

(12) 阿里云RDS数据库误操作损毁,完整备份恢复实操避坑指南

为了看起来更完善,AI会主动新增非必要的清理、校验、适配逻辑,简单需求复杂化,大幅增加报错和风险概率(如图7)

(13) AI生成代码深度避坑:数据库操作代码绝不可以直接上线执行

WordPress 标签清理实践(一):大语言模型匹配的失败尝试

(14) WordPress 标签清理实践(一):大语言模型匹配的失败尝试

在宿主机的 output 目录下可以找到生成的 tag_mapping_result.csv。打开文件查看,结果格式规整,符合预期。

(15) WordPress 标签清理实践(二):Go 脚本工程化落地

脚本执行后(如 图 6 终端日志所示),系统开始成对合并中英文标签。

(16) WordPress 标签清理实践(三):完美解决Polylang中英文同义标签合并难题

图7:展示了浏览器开发者工具Network面板中,旧URL 301跳转至新URL的成功记录

(17) WordPress 标签清理实践(四):基于Go脚本实现WordPress中英文标签合并与URL自动跳转

截图 5:验证 301 跳转

(18) WordPress 标签清理实践(五):基于 PHP/Go 脚本解决 English 语言下残留的中文标签问题 ,并实现自动化的标签合并与 URL 跳转

脚本显示处理了 8324 个标签

(19) WP 标签批量翻译脚本准确性问题排查与修复

图5:DeepL API 注册页面,国家或地区列表中没有中国大陆

(20) 中国大陆 WordPress 博客想提升英文翻译质量,为什么这么麻烦?一次 Polylang + AutoPoly + DeepL API 排查复盘

图5:DeepSeek 的评分结果截图

(21) Chrome Built-in AI、Yandex Translate、ChatGPT Plus 翻译质量对比:我为什么决定重点英文文章改用 ChatGPT Plus

[截图 2:浏览器 Network 中直接请求 translate.yandex.net]

(22) 从 AutoPoly 到 Yandex 网页版:一次 WordPress 英文自动翻译质量验证

【图1:AutoPoly Free 与 Pro 功能对比截图】

(23) AutoPoly Pro + OpenAI API 能否自动化 WordPress 英文翻译?一次从技术到支付的可行性分析

【图2:点击“立即试用”后,ChatGPT 输入框中出现“代理模式”】

(24) ChatGPT Agent 能否替代 ChatGPT Plus 完成 WordPress 英文重译?

【图 1,英文首页日历日期链接被拼接成双重 URL】

(25) WordPress 英文站日历链接变成双重 URL:Polylang 子域名迁移后的 WPCode 与 W3TC Object Cache 排查

【图 7,数据库原始内容与 get_post() 返回内容不一致】

(26) WordPress 英文站出现横向滚动条:排查 Polylang 多域名下 W3TC Object Cache 缓存旧 CSS 的问题

【图 1,主题编辑器中的分类列表区块及“以下拉菜单显示”设置】

(27) WordPress Polylang 英文子域名迁移后链接仍指向中文站:分类下拉、面包屑与区块模板的完整修复

【图 1,终端检查 www 与 en 域名统计代码的结果】

(28) WordPress 英文站从 /en/ 迁移到子域名后,如何调整 GA4 与百度统计

【图 7,SlyTranslate 显示翻译完成并创建文章 19426】

(29) SlyTranslate + 智谱 GLM-5.2 长文翻译排障:从 600 秒超时到完整生成英文 WordPress 文章

WordPress 多域名架构下 W3 Total Cache 缓存失效:Polylang、Redis 与 admin 子域名的完整排查和修复

(30) WordPress 多域名架构下 W3 Total Cache 缓存失效:Polylang、Redis 与 admin 子域名的完整排查和修复

最近,我将 WordPress 英文站从原来的 /en/ 路径迁移到了独立子域名:

Plaintext
中文站:www.shuijingwanwq.com
英文站:en.shuijingwanwq.com
后台:admin.shuijingwanwq.com

三个域名共用同一套 WordPress 程序、数据库和 Redis,但分别承担不同职责:

  • www:中文前台,通过 EdgeOne;
  • en:英文前台,通过 Cloudflare;
  • admin:WordPress 后台,直接连接源站;
  • 多语言插件:Polylang;
  • 页面缓存:W3 Total Cache Disk Enhanced;
  • 对象缓存:W3 Total Cache Redis Object Cache;
  • 自定义代码:WPCode。

这套架构在访问、后台升级和 CDN 流量控制方面都达到了预期效果,但很快暴露出一个比较隐蔽的问题:

admin 后台发布文章、修改 WPCode 片段或清理缓存后,wwwen 并不一定能够同步获得最新内容。

经过多轮源码分析、缓存对照和受控测试,最终确认问题并不是单一的“页面缓存没有清理”,而是 W3 Total Cache 在多域名环境下同时存在:

  1. Page Cache 清理 URL 不完整;
  2. Redis Object Cache 按 Host 隔离;
  3. 后台保存发生在 admin Host,前台缓存却存放在 wwwen Host;
  4. W3TC 原生缓存组版本与单个对象缓存键的 Host 规则并不完全一致。

本文记录完整的排查过程与最终修复方案。


一、问题表现

1. 发布英文文章后,英文首页没有出现新文章

通过 admin.shuijingwanwq.com 发布英文文章后:

  • 英文文章详情页可以访问;
  • 文章数据库状态正常;
  • 英文首页仍然保留旧文章列表。

W3TC 会清理文章详情页,也会清理一个首页,但它计算首页 URL 时受到当前后台 Host 和 Polylang 语言上下文影响。

结果是:

Plaintext
保存英文文章
→ 英文文章详情缓存被删除
→ 中文首页可能被删除
→ 英文首页缓存没有被删除

2. 中文首页重新生成后,仍然缺少最新两篇文章

后来又发现,即使中文首页 Page Cache 文件已经被删除,重新访问首页后,页面仍然缺少最新两篇文章。

当时最新的中文文章是:

Plaintext
19440
19429

但中文首页仍然从 19419 开始显示。

这说明问题已经不仅是 Page Cache。

3. 修改 WPCode 片段后,英文页面仍执行旧代码

我在 WPCode 中修复了一个未初始化变量:

Plaintext
$current_lang         = '';
$current_series_slugs = array();

后台和中文站已经读取到新代码,但英文站仍然执行旧版本。

三个 Host 的 WPCode 缓存对比结果为:

Plaintext
admin:包含新初始化代码
www:  包含新初始化代码
en:   不包含新初始化代码

英文测试文章中的 CTA 数量仍然为:

Plaintext
0

这证明英文 Host 的 Redis Object Cache 没有同步失效。


二、先区分 Page Cache、Object Cache 与 CDN

整个排查过程中,首先要避免把所有“页面没更新”都归因于 CDN。

我分别抓取了三份中文首页:

Plaintext
1. 直连源站动态页面
2. EdgeOne 正常首页
3. EdgeOne 带随机参数的页面

结果显示三份页面都缺少相同的两篇文章。

同时,EdgeOne 响应状态为:

Plaintext
eo-cache-status: MISS

这意味着 EdgeOne 当时并没有返回旧的边缘缓存,而是正常回源。

因此问题位于 WordPress 源站内部。


三、对比正常查询与绕过缓存查询

为了确认是否为 Redis 查询缓存问题,我分别执行了:

Plaintext
cached
uncached

两种 WordPress 首页查询。

www Host 下的缓存查询结果:

Plaintext
found_posts:1312

首页前两篇:
19419
19406

强制禁用查询缓存后的结果:

Plaintext
found_posts:1314

首页前两篇:
19440
19429

这一步直接证明:

数据库中的文章正常,Polylang 查询正常,真正陈旧的是 www Host 下的 WordPress 查询对象缓存。

更明显的是,三个 Host 的 posts:last_changed 完全不同:

Plaintext
admin:0.97323000 1784020979
www:  0.94302500 1783993649
en:   0.97440600 1784019451

也就是说,同一个 WordPress 单站已经形成了三套互相独立的文章查询缓存。


四、W3 Total Cache 为什么会生成三套 Redis 缓存

继续查看 W3 Total Cache 源码后发现,Object Cache 的普通缓存键最初由以下内容组成:

PHP
return $blog_id . $w3tc_group . $id;

但在创建 Redis 实例时,W3TC 还会传入:

PHP
$engine_config['blog_id']     = $blog_id;
$engine_config['module']      = 'object';
$engine_config['host']        = Util_Environment::host();
$engine_config['instance_id'] = Util_Environment::instance_id();

最终 Redis 存储键的公式为:

Plaintext
return sprintf(
    'w3tc_%d_%s_%d_%s_%s',
    $this->_instance_id,
    $this->_host,
    $this->_blog_id,
    $this->_module,
    $w3tc_name
);

也就是:

Plaintext
w3tc_{instance_id}_{host}_{blog_id}_{module}_{name}

在当前单站环境中,blog_id 实际为 0,真正导致缓存分裂的是 Host:

Plaintext
w3tc_0_admin.shuijingwanwq.com_0_object_...
w3tc_0_www.shuijingwanwq.com_0_object_...
w3tc_0_en.shuijingwanwq.com_0_object_...

因此:

Plaintext
后台保存文章
→ admin Host 的对象缓存发生变化
→ www Host 仍然保留旧对象
→ en Host 仍然保留旧对象

这不是 Polylang 主动生成的,也不是我已有的 MU Plugin 设置了不同 Salt,而是 W3 Total Cache Object Cache 的 Host 隔离机制。


五、为什么不能直接让三个域名共享 Object Cache

看到 Host 隔离后,一个很自然的想法是:

是否可以删除 Host,让三个域名共享同一套 Redis Object Cache?

我最终没有采用这个方案。

原因是 wwwen 并不是内容完全相同的镜像域名,而是 Polylang 的不同语言站点:

Plaintext
www:中文语言上下文
en: 英文语言上下文

两者可能存在不同的:

  • lang
  • canonical;
  • hreflang;
  • 菜单;
  • 分类;
  • 首页文章列表;
  • 全局样式;
  • Polylang 配置对象。

之前英文站出现中文 <html lang>、canonical 指向中文站、分类跳转错误和旧全局样式,都与跨域对象缓存边界有关。

因此,更安全的方向不是取消 Host 隔离,而是:

保留三个 Host 的独立缓存对象,在必要时同步提升缓存组版本,使旧缓存整体失效。


六、W3TC 缓存组版本键恰好不包含 Host

W3TC 的普通对象缓存键包含 Host,但缓存组版本键格式为:

PHP
return sprintf(
    'w3tc_%d_%d_%s_%s_key_version',
    $this->_instance_id,
    $this->_blog_id,
    $this->_module,
    $w3tc_group
);

格式为:

Plaintext
w3tc_{instance_id}_{blog_id}_{module}_{group}_key_version

这里没有 Host。

W3TC 的 Redis flush() 实现并不是遍历删除所有键,而是递增缓存组版本:

PHP
public function flush( $w3tc_group = '' ) {
    $this->_get_key_version( $w3tc_group );

    if ( isset( $this->_key_version[ $w3tc_group ] ) ) {
        ++$this->_key_version[ $w3tc_group ];

        $this->_set_key_version(
            $this->_key_version[ $w3tc_group ],
            $w3tc_group
        );
    }

    return true;
}

因此执行:

PHP
wp_cache_flush_group( 'posts' );

可以一次性让三个 Host 下旧的 posts 对象失效,而不需要清空整个 Redis 数据库。


七、受控测试:同步失效 posts 缓存组

我先记录三个 Host 的 posts:last_changed,然后从 admin 上下文执行:

PHP
wp_cache_flush_group( 'posts' );

执行结果为:

Plaintext
支持 flush_group:是
执行结果:true

随后重新查询三个 Host。

中文站结果从:

Plaintext
found_posts:1312

恢复为:

Plaintext
found_posts:1314

首页重新出现:

Plaintext
19440
19429

英文站的语言上下文和文章列表仍然正常。

这证明:

使用缓存组版本失效,可以在保留 Host 隔离的同时,解决后台保存后前台查询缓存不更新的问题。


八、Page Cache 的另一个缺口:语言首页没有加入清理队列

W3TC 保存文章时会调用:

Plaintext
save_post
→ w3tc_flush_post()
→ PgCache_Flush::flush_post()
→ 生成需要清理的 URL
→ 延迟执行 Page Cache 删除

文章详情页 URL 可以根据文章语言正确生成,但首页 URL 的计算依赖当前请求 Host。

当后台请求来自:

Plaintext
admin.shuijingwanwq.com

W3TC 并不会始终把对应语言首页加入清理队列。

因此需要在 W3TC 原生 w3tc_flush_post 回调之后,额外加入当前文章语言的首页:

PHP
$language = pll_get_post_language(
    $post_id,
    'slug'
);

$language_home = pll_home_url(
    $language
);

w3tc_flush_url(
    trailingslashit( $language_home )
);

W3TC 原生处理优先级为 1100,补充回调放在 1200,这样可以在延迟清理执行前追加 URL。


九、WPCode 缓存为什么也会在 en Host 中过期

WPCode 会把已经加载的活动片段统一存入:

Plaintext
wpcode_snippets

其缓存类通过:

PHP
get_option( 'wpcode_snippets' )

读取数据。

get_option() 会经过 WordPress Object Cache 的 options 缓存组。

因此在多 Host 环境下,实际形成:

Plaintext
admin Host 的 options 缓存
www Host 的 options 缓存
en Host 的 options 缓存

我修改 WPCode 片段后,数据库与 adminwww 已经是最新版,但 en 仍然保留旧对象。

当时三个 Host 的序列化缓存结果为:

Plaintext
admin:
SHA256:b531ca1288a6cd31179bb61ad6ca48593315e44bfc26048607d8ed7d1a243560
包含初始化语句:是

www:
SHA256:b531ca1288a6cd31179bb61ad6ca48593315e44bfc26048607d8ed7d1a243560
包含初始化语句:是

en:
SHA256:c765320e9ccc3fe0bbf9daafb16554c4c5023b19916d5fd3bcc257ca2277d14c
包含初始化语句:否

英文测试文章中的 CTA 数量为:

Plaintext
0

十、不监听 WPCode 保存,继续保留手动清缓存习惯

最初也考虑过:

Plaintext
保存 WPCode
→ 自动清全部 Page Cache

但这没有必要。

以前只有 www 一个域名时,我的习惯就是:

Plaintext
保存 WPCode
→ 手动清除缓存

多域名以后,理想方案应该保持相同使用习惯:

Plaintext
保存 WPCode
→ 性能
→ 清除模块
→ 对象缓存
→ 清除模块
→ 页面缓存

不需要让每次 WPCode 保存都自动清理整个站点,也不需要每次都清除操作码缓存。


十一、将 options 组同步挂到对象缓存清理之后

W3TC 清除对象缓存的流程为:

Plaintext
do_action( 'w3tc_flush_objectcache' );

$objectcache->flush();

do_action( 'w3tc_flush_after_objectcache' );

因此最合适的 Hook 是:

PHP
w3tc_flush_after_objectcache

它同时覆盖:

Plaintext
性能 → 清除模块 → 对象缓存
性能 → 清除所有缓存

在该 Hook 中执行:

PHP
wp_cache_flush_group( 'options' );

可以让三个 Host 的 options 缓存同时失效。

这个处理:

  • 不监听 WPCode 保存;
  • 不主动清 Page Cache;
  • 不清空整个 Redis;
  • 不影响其他对象缓存组;
  • 不清除操作码缓存。

十二、最终 MU Plugin 完整代码

最终文件:

Plaintext
wp-content/mu-plugins/swq-w3tc-polylang-purge.php

版本为 1.3.0

PHP
<?php
/**
 * Plugin Name: SWQ W3TC Polylang Purge
 * Description: Completes W3 Total Cache Page Cache and Object Cache invalidation for a Polylang multi-domain site.
 * Version: 1.3.0
 */

defined( 'ABSPATH' ) || exit;

/**
 * Add the post language homepage to W3TC's current Page Cache purge queue.
 *
 * W3TC registers its native w3tc_flush_post callback at priority 1100.
 * This callback runs afterwards and appends the missing language homepage
 * before W3TC executes its delayed Page Cache cleanup.
 *
 * @param int        $post_id Post ID being flushed.
 * @param bool       $force   Whether W3TC forced the purge.
 * @param mixed|null $extras  Additional W3TC purge information.
 */
function swq_w3tc_polylang_queue_language_home(
    $post_id,
    $force = false,
    $extras = null
) {
    $post_id = (int) $post_id;

    if (
        $post_id < 1
        || ! function_exists( 'w3tc_flush_url' )
        || ! function_exists( 'pll_get_post_language' )
        || ! function_exists( 'pll_home_url' )
    ) {
        return;
    }

    $post = get_post( $post_id );

    if ( ! $post || 'post' !== $post->post_type ) {
        return;
    }

    $language = pll_get_post_language(
        $post_id,
        'slug'
    );

    if ( ! is_string( $language ) || '' === $language ) {
        return;
    }

    $language_home = pll_home_url( $language );

    if (
        ! is_string( $language_home )
        || '' === $language_home
    ) {
        return;
    }

    w3tc_flush_url(
        trailingslashit( $language_home ),
        array(
            'swq_source' => 'polylang_language_home',
            'post_id'    => $post_id,
            'language'   => $language,
        )
    );
}

add_action(
    'w3tc_flush_post',
    'swq_w3tc_polylang_queue_language_home',
    1200,
    3
);

/**
 * Invalidate the shared W3TC Redis version for the WordPress posts group.
 *
 * W3TC places the request Host in individual Redis object keys. As a result,
 * saving a post through admin.shuijingwanwq.com normally invalidates only the
 * admin Host's posts:last_changed value, leaving www and en query caches stale.
 *
 * W3TC's Redis group-version key does not contain the Host. Flushing the posts
 * group therefore invalidates stale post queries across all three Hosts,
 * without flushing the entire Redis database or unrelated cache groups.
 *
 * @param int        $post_id Post ID being flushed.
 * @param bool       $force   Whether W3TC forced the purge.
 * @param mixed|null $extras  Additional W3TC purge information.
 */
function swq_w3tc_sync_posts_object_cache_group(
    $post_id,
    $force = false,
    $extras = null
) {
    static $flushed = false;

    if ( $flushed ) {
        return;
    }

    $post_id = (int) $post_id;

    if (
        $post_id < 1
        || ! function_exists( 'wp_cache_flush_group' )
        || ! function_exists( 'wp_cache_supports' )
        || ! wp_cache_supports( 'flush_group' )
    ) {
        return;
    }

    $post = get_post( $post_id );

    if ( ! $post || 'post' !== $post->post_type ) {
        return;
    }

    /*
     * Prevent repeated group-version increments when W3TC triggers more than
     * one post purge during the same WordPress request.
     */
    $flushed = true;

    wp_cache_flush_group( 'posts' );
}

add_action(
    'w3tc_flush_post',
    'swq_w3tc_sync_posts_object_cache_group',
    1250,
    3
);

/**
 * Invalidate Host-separated options caches after W3TC Object Cache is flushed.
 *
 * W3TC includes the current Host in individual Object Cache keys. Its normal
 * Object Cache purge therefore invalidates only the current Host namespace.
 *
 * The Redis group-version key does not include the Host. Flushing the options
 * group makes admin, www and en reload options such as WPCode's
 * wpcode_snippets data from the shared database.
 *
 * This callback runs after either:
 *
 * - Purge Module: Object Cache
 * - Purge All Caches
 *
 * It does not initiate a Page Cache or opcode-cache purge.
 */
function swq_w3tc_sync_options_group_after_objectcache_flush() {
    if (
        ! function_exists( 'wp_cache_flush_group' )
        || ! function_exists( 'wp_cache_supports' )
        || ! wp_cache_supports( 'flush_group' )
    ) {
        return;
    }

    wp_cache_flush_group( 'options' );
}

add_action(
    'w3tc_flush_after_objectcache',
    'swq_w3tc_sync_options_group_after_objectcache_flush',
    10,
    0
);

十三、最终验证结果

1. 保存文章后的 Page Cache

执行中文文章缓存清理后:

Plaintext
中文首页 HTML:不存在
中文首页 GZIP:不存在

中文文章 HTML:不存在
中文文章 GZIP:不存在

英文首页 HTML:仍然存在
英文首页 GZIP:仍然存在

说明中文文章更新时:

  • 中文文章详情缓存被删除;
  • 中文首页缓存被删除;
  • 英文首页未被误删。

2. posts 查询缓存

清理后 www 首页恢复为:

Plaintext
found_posts:1314

首页前两篇:
19440
19429

3. WPCode 对象缓存

执行:

Plaintext
性能 → 清除模块 → 对象缓存

之后三个 Host 的 WPCode 缓存完全一致:

Plaintext
大小:71475

SHA256:
b531ca1288a6cd31179bb61ad6ca48593315e44bfc26048607d8ed7d1a243560

包含初始化语句:是

英文测试文章中的 CTA 数量也从:

Plaintext
0

恢复为:

Plaintext
1

4. Page Cache 模块清理

执行:

Plaintext
性能 → 清除模块 → 页面缓存

后检查:

Plaintext
中文首页:有效 HTML/GZIP 不存在
英文首页:有效 HTML/GZIP 不存在
中文文章:有效缓存不存在
英文文章:有效缓存不存在

部分缓存文件会变成:

Plaintext
_index_slash_ssl.html_old
_index_slash_ssl.html_gzip_old

这是 W3TC 的正常清理过程。

清理后看到少量新的有效缓存文件,也不代表清理失败,因为网站仍然会被用户、搜索引擎和爬虫访问,页面会立即重新生成。


十四、页面缓存别名与对象缓存全局组能否替代插件

在 W3TC 设置中,还可以看到两个看起来与多域名有关的功能:

Plaintext
页面缓存 → 缓存别名主机名
对象缓存 → 全局组

但它们不能直接替代当前方案。

缓存别名主机名

这个功能更适合同一份内容通过多个镜像域名访问,例如:

Plaintext
example.com/article/
mirror.example.com/article/

而当前:

Plaintext
www = 中文
en  = 英文

不是镜像关系。

中英文站拥有不同的:

  • 内容;
  • URL;
  • 语言上下文;
  • 首页;
  • canonical;
  • 分类与菜单。

因此不应该把 wwwen 简单设置为页面缓存别名。

对象缓存全局组

“全局组”主要解决 WordPress Multisite 中不同站点之间的缓存组共享。

当前是普通 WordPress 单站,而且 W3TC 最终 Redis 键中仍然包含 Host。

即使把 postsoptions 加入全局组,也不能自动移除:

Plaintext
admin.shuijingwanwq.com
www.shuijingwanwq.com
en.shuijingwanwq.com

这一层 Host 隔离。

因此,目前仍然需要 MU Plugin 对特定缓存组进行同步失效。


十五、现在的日常操作方式

发布或更新普通文章

正常情况下不再需要手动清缓存:

Plaintext
后台保存文章
→ W3TC 清理文章详情页
→ MU Plugin 补充清理对应语言首页
→ MU Plugin 同步失效 posts 对象缓存组

修改 WPCode 片段

继续保留以前的手动操作习惯:

Plaintext
性能
→ 清除模块
→ 对象缓存

性能
→ 清除模块
→ 页面缓存

不需要清理:

Plaintext
操作码缓存

也不一定需要每次都执行:

Plaintext
清除所有缓存

十六、当前方案的边界

本次已经完整验证:

  • WordPress 源站 Page Cache;
  • W3TC Redis Object Cache;
  • Polylang 中英文语言首页;
  • admin、www、en 三 Host;
  • WPCode 活动代码缓存;
  • 页面缓存模块清理;
  • 对象缓存模块清理。

EdgeOne 当前返回 MISS 时,公网首页和源站内容已经一致。

不过,本文没有单独完成下面这个 CDN 场景的闭环测试:

Plaintext
EdgeOne 已经 HIT
→ 后台更新文章
→ 是否主动刷新边缘 HTML

这属于 CDN 层面的缓存刷新问题,与本文处理的 W3TC、Redis 和 Polylang 源站缓存问题并不相同。

如果后续再次发现:

Plaintext
源站已经更新
EdgeOne 仍然返回旧页面

再单独处理 EdgeOne API 或 WordPress 自动刷新机制会更合适。


十七、总结

这次问题最容易产生误判的地方是:

Page Cache 文件已经删除,并不代表页面一定会生成最新内容。

在当前多域名架构中,完整链路是:

Plaintext
数据库
→ WordPress 查询缓存
→ WPCode / options 对象缓存
→ W3TC Page Cache
→ CDN

只清除其中一层,页面仍然可能继续显示旧内容。

最终解决方案没有取消 W3TC 的 Host 隔离,也没有粗暴清空整个 Redis,而是利用 W3TC 本身的缓存组版本机制:

PHP
wp_cache_flush_group( 'posts' );
wp_cache_flush_group( 'options' );

这样既保留了 Polylang 多域名之间必要的隔离,又能够在关键操作发生时,让 adminwwwen 同步放弃旧缓存。

对于当前这套 WordPress、Polylang、W3 Total Cache、Redis 与多 CDN 架构来说,这比完全共享 Object Cache 或频繁执行 Redis Flush 更安全,也更容易维护。

WordPress 英文站从 /en/ 迁移到子域名后,如何调整 GA4 与百度统计

WordPress 网站维护、性能优化与博客运营咨询

本站已持续运营超过 10 年,累计发布 1000+ 篇原创技术文章,长期实践 WordPress 网站建设、CDN / Cloudflare 配置、缓存优化、Google SEO、广告变现和多语言网站运营。

如果你的 WordPress 网站遇到访问慢、缓存异常、插件冲突、广告不显示、SEO 基础结构混乱、CDN 配置不确定等问题,可以联系我做一次远程技术排查。

适合以下用户:
✅ 个人博客站长
✅ WordPress 网站运营者
✅ 独立开发者与内容创作者
✅ SaaS 产品官网运营团队
✅ 希望优化网站速度与稳定性的站点

服务内容:
✅ WordPress 速度优化
✅ Cloudflare / CDN / 缓存配置排查
✅ 插件冲突与页面异常排查
✅ AdSense 广告显示问题排查
✅ SEO 基础结构检查
✅ 博客运营与商业化咨询

如需了解方案或交流相关问题,请直接联系我,并注明:WordPress 维护咨询

联系方式:
Telegram:@shuijingwan
微信:13980074657
邮箱:shuijingwanwq@gmail.com

评论

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

这个站点使用 Akismet 来减少垃圾评论。了解你的评论数据如何被处理