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

解决 WordPress + Polylang 批量处理标签时遇到的 Redis OOM 错误

PHP Fatal error: Uncaught RedisException: OOM command not allowed when used memory > 'maxmemory'. in /data/wwwroot/.../wp-content/plugins/w3-total-cache/Cache_Redis.php:150

WordPress 性能优化手记

如 如图1 所示,站点健康直接提示这是一个可能对性能或安全性产生重大影响的问题,需要优先解决。

(1) 从站点健康警告到全绿通关

PHP Fatal error: Uncaught RedisException: OOM command not allowed when used memory > 'maxmemory'. in /data/wwwroot/.../wp-content/plugins/w3-total-cache/Cache_Redis.php:150

(2) 解决 WordPress + Polylang 批量处理标签时遇到的 Redis OOM 错误

采用 ondemand 模式,适合 1 核小内存机器,空闲时释放进程。最终配置如下:如图4

(3) 一次WordPress站点504错误的排查与优化实录

优化前最终基准数据:历史累计504错误129条(6月3日峰值126条,为爬虫批量爬标签导致)。

(4) 从单日126次504超时到彻底稳定:WordPress 1核2G服务器极限优化全记录(附全部实操命令)

WebPageTest 核心指标

(5) WordPress性能基准测试与CDN选型实录:从国内拨测到海外WebPageTest,1核2G服务器如何面向全球

页面底部提示“此响应不是合法的 JSON 响应”。

(6) WordPress 标签保存失败?Nginx 限流规则惹的祸 —— 一次完整的 429 问题排查与解决

表示页面仍然是动态生成,没有缓存命中。

(7) WordPress + Nginx + W3 Total Cache 缓存未生效排查全过程(OneinStack 实战)

图7:带 Query String 后,W3TC 显示 Requested URI contains query

(8) WordPress CPU 再次满载:动态参数如何穿透 CDN 与 W3TC 页面缓存

图1:阿里云 ECS 在 14:33~14:42 期间 CPU 使用率持续接近 100%,而内存使用率整体较为稳定

(9) WordPress 服务器 CPU 再次满载:从 Nginx 499、PHP-FPM、Redis 到 W3TC 冷缓存的完整排查

图4:W3TC 最终使用 300 秒 × 7 页,并切换到中英文联合 Sitemap

(10) 从 CPU 告警到双域名预缓存:W3 Total Cache、EdgeOne 与 Cloudflare 96 小时缓存优化实战

WordPress 所有归档模板中使用 Language Visibility 和 WPCode Shortcode 添加中英文 Adsterra 广告

(11) WordPress 三域名架构再次踩坑:Adsterra 归档广告不生效,最终定位到 W3TC Object Cache

WordPress 多语言多域名缓存排查:修复 Polylang + W3 Total Cache 跨 Host 缓存失效问题

(12) WordPress 多语言多域名缓存排查:修复 Polylang + W3 Total Cache 跨 Host 缓存失效问题

WordPress 多域名环境下中文文章详情页未显示 Polylang 语言切换器

(13) WordPress 多域名下 Polylang 语言切换器延迟:W3TC Redis 跨 Host 缓存排查记录

图8:选择 2 核 4 GiB 后显示的实际补差价、2 Mbps 带宽和重启选项

(14) 从 CPU 再次告警到 ECS 升配:WordPress 服务器从 1 核 2G 升级到 2 核 4G 实录

**Alt:** WordPress 生产环境完成 PHP 8.5.9 升级,终端显示 OPcache、Imagick、Redis、Nginx、WordPress 版本及中英文站和后台域名均正常返回 HTTP 200

(15) OneinStack 生产环境将 PHP 8.1.19 升级到 PHP 8.5.9:Imagick 编译失败与 WordPress 多域名缓存验收

阿里云 OneinStack 服务器升级完成,终端显示 Nginx 1.30.4、OpenSSL 3.5.7、PCRE 8.45 和 PHP 8.5.9,Nginx 配置检查成功

(16) 阿里云 OneinStack 实战:将 Nginx 1.24.0 升级到 1.30.4,并同步升级 OpenSSL 3.5.7

阿里云 OneinStack 服务器 Redis 从 7.0.11 升级到 8.10.0 后的版本与运行状态对比截图

(17) 阿里云 OneinStack 实战:将 Redis 7.0.11 升级到 8.10.0,并完成内核优化与回滚保护

GitHub 上为 PublishPress Series 提交 PHP 8.5 SplObjectStorage 弃用警告 Issue 的页面

(18) WordPress 升级 PHP 8.5 后的插件兼容性排查:该修的修,该停的停,该等上游的等

WordPress Post Views Counter 热门文章排行榜区块及浏览量设置界面,用于排查首页查询性能问题

(19) WordPress 动态首页从 19 秒降到 1 秒以内:Post Views Counter 热门文章查询性能问题排查与 MU Plugin 优化实战

WordPress 撰写设置中已开启可能影响网站性能的 Gutenberg 实时协作功能

(20) WordPress 7.0 + PHP 8.5 服务器配置全面审计:PHP-FPM、OPcache、Redis、RDS 与 WordPress 调优实战

【图 1:8 月 6 日提交的 PublishPress Series PHP 8.5 兼容性 Issue #1163 已由上游关闭】

(21) PublishPress Series 3.1.3 升级实录:PHP 8.5 Issue 已修复,却又遇到 Gutenberg 系列编号回归

一、问题背景

我运营着一个基于 WordPress 的双语网站(中文/英文),使用了 Polylang 插件来管理多语言内容。为了批量给已有的中文分类/标签创建对应的英文翻译,我写了一个 PHP 脚本 polylang-batch-zh-to-en-tags.php

然而,在执行脚本时,终端突然报出致命错误:

Plaintext
[root@iZ23wv7v5ggZ www.shuijingwanwq.com]# php polylang-batch-zh-to-en-tags.php
PHP Fatal error:  Uncaught RedisException: OOM command not allowed when used memory > 'maxmemory'. in /data/wwwroot/www.shuijingwanwq.com/wp-content/plugins/w3-total-cache/Cache_Redis.php:150
Stack trace:
#0 /data/wwwroot/www.shuijingwanwq.com/wp-content/plugins/w3-total-cache/Cache_Redis.php(150): Redis->setex()
#1 /data/wwwroot/www.shuijingwanwq.com/wp-content/plugins/w3-total-cache/DbCache_WpdbInjection_QueryCaching.php(253): W3TC\Cache_Redis->set()
#2 /data/wwwroot/www.shuijingwanwq.com/wp-content/plugins/w3-total-cache/DbCache_WpdbNew.php(216): W3TC\DbCache_WpdbInjection_QueryCaching->query()
#3 /data/wwwroot/www.shuijingwanwq.com/wp-includes/class-wpdb.php(3150): W3TC\DbCache_WpdbNew->query()
#4 /data/wwwroot/www.shuijingwanwq.com/wp-includes/taxonomy.php(4123): wpdb->get_results()
#5 /data/wwwroot/www.shuijingwanwq.com/wp-includes/class-wp-term-query.php(825): _prime_term_caches()
#6 /data/wwwroot/www.shuijingwanwq.com/wp-includes/class-wp-term-query.php(308): WP_Term_Query->get_terms()
#7 /data/wwwroot/www.shuijingwanwq.com/wp-includes/taxonomy.php(1357): WP_Term_Query->query()
#8 /data/wwwroot/www.shuijingwanwq.com/wp-includes/taxonomy.php(2338): get_terms()
#9 /data/wwwroot/www.shuijingwanwq.com/wp-includes/taxonomy.php(3856): wp_get_object_terms()
#10 /data/wwwroot/www.shuijingwanwq.com/wp-content/plugins/polylang/src/translated-term.php(250): update_object_term_cache()
#11 /data/wwwroot/www.shuijingwanwq.com/wp-includes/class-wp-hook.php(343): PLL_Translated_Term->_prime_terms_cache()
#12 /data/wwwroot/www.shuijingwanwq.com/wp-includes/plugin.php(205): WP_Hook->apply_filters()
#13 /data/wwwroot/www.shuijingwanwq.com/wp-includes/taxonomy.php(1379): apply_filters()
#14 /data/wwwroot/www.shuijingwanwq.com/polylang-batch-zh-to-en-tags.php(28): get_terms()
#15 {main}
  thrown in /data/wwwroot/www.shuijingwanwq.com/wp-content/plugins/w3-total-cache/Cache_Redis.php on line 150

脚本直接崩溃,无法继续处理。如图1

脚本直接崩溃,无法继续处理。如图1

二、错误分析

从错误信息可以看出:

  • 抛出位置:W3 Total Cache 插件的 Redis 缓存驱动。
  • 直接原因:Redis 返回了 OOM command not allowed,表示 Redis 的内存使用已超过 maxmemory 限制,并且配置策略为 禁止任何写入noeviction)。
  • 间接原因:脚本执行过程中会触发 WordPress 的术语缓存更新(_prime_term_caches),进而调用了 W3 Total Cache 的对象缓存,向 Redis 写入数据。

关键线索:Redis 的内存淘汰策略为 noeviction。这意味着一旦内存占用达到上限,所有写操作都会被拒绝,直到内存被手动清理。

三、排查步骤

1. 检查 Redis 当前内存状态

检查 Redis 当前内存状态
Plaintext
redis-cli INFO memory | grep -E "maxmemory|used_memory|maxmemory_policy"

输出如下:

Plaintext
used_memory:33107888
used_memory_human:31.57M
maxmemory:120000000
maxmemory_human:114.44M
maxmemory_policy:noeviction

可以看到:

  • 最大内存仅为 114 MB(对于现代 WordPress + 多插件环境来说明显偏小)。
  • 淘汰策略为 noeviction(罪魁祸首)。

2. 查看服务器整体内存情况

查看服务器整体内存情况
Bash
free -h

结果:

Plaintext
              total        used        free      shared  buff/cache   available
Mem:          1.9Gi       321Mi       184Mi        90Mi       1.4Gi       1.3Gi
Swap:         2.0Gi       130Mi       1.9Gi

服务器总内存约 2GB,可用物理内存充足(1.3GB),完全可以分配给 Redis 更多空间。

四、解决方案

1. 临时修复(立即生效,无需重启)

Bash
redis-cli CONFIG SET maxmemory 1024mb
redis-cli CONFIG SET maxmemory-policy allkeys-lru
  • maxmemory 1024mb:将 Redis 最大内存提升至 1GB。
  • maxmemory-policy allkeys-lru:当内存用满时,自动淘汰 最近最少使用 的键。

2. 永久生效(修改配置文件)

由于我的 Redis 是通过 OneinStack 编译安装的,配置文件位于 /usr/local/redis/etc/redis.conf

Bash
vim /usr/local/redis/etc/redis.conf

找到或添加以下两行:

找到或添加以下两行:
Bash
maxmemory 1024mb
maxmemory-policy allkeys-lru

保存后重启 Redis(OneinStack 的服务名是 redis-server):

Bash
service redis-server restart

3. 验证修改

Bash
redis-cli CONFIG GET maxmemory
# 输出:1073741824 (即 1GB)

redis-cli CONFIG GET maxmemory-policy
# 输出:allkeys-lru

五、最终结果

再次执行批量处理脚本:

Bash
php polylang-batch-zh-to-en-tags.php

输出:

Plaintext
🚀 开始批量处理所有zh标签,自动添加en翻译(分页模式)...
📊 正在处理第 1 - 1000 个标签...
📊 正在处理第 1001 - 2000 个标签...
...
🎉 全部处理完成!
📊 统计:
   已处理新标签: 0
   已跳过已有翻译: 8289
✅ 所有标签都已经处理完毕,和手动添加的完全一样!

不再有任何 Redis 错误,脚本顺利运行完成!

六、经验总结

  1. Redis 默认的 noeviction 策略并不适合缓存场景,尤其是在有限内存环境下。推荐使用 allkeys-lruvolatile-lru
  2. WordPress + W3 Total Cache + Redis 对象缓存会大量消耗内存,务必根据服务器实际情况设置合理的 maxmemory
  3. OneinStack 安装的 Redis 服务名是 redis-server,而不是常见的 redisredis.service,管理时需要注意。
  4. 批量操作触发大量缓存写入时,可以临时禁用对象缓存(define('DONOTCACHEOBJECT', true);),但更好的做法是调整 Redis 策略让系统自动适应。

七、延伸建议

  • 若网站流量增长,可将 maxmemory 进一步提升至 1.5GB ~ 2GB(视总内存而定)。
  • 定期监控 Redis 内存使用:redis-cli --stat 或集成 redis_exporter + Prometheus。
  • W3 Total Cache 的对象缓存可适当缩短“垃圾回收间隔”(如 3600 秒),避免过期键堆积。

希望这篇博客能帮助到遇到类似问题的朋友。如果你们也有关于 Redis + WordPress 的踩坑经历,欢迎在评论区交流讨论!

从站点健康警告到全绿通关 一次WordPress站点504错误的排查与优化实录

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