解决 WordPress + Polylang 批量处理标签时遇到的 Redis OOM 错误
一、问题背景
我运营着一个基于 WordPress 的双语网站(中文/英文),使用了 Polylang 插件来管理多语言内容。为了批量给已有的中文分类/标签创建对应的英文翻译,我写了一个 PHP 脚本 polylang-batch-zh-to-en-tags.php。
然而,在执行脚本时,终端突然报出致命错误:
[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

二、错误分析
从错误信息可以看出:
- 抛出位置: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-cli INFO memory | grep -E "maxmemory|used_memory|maxmemory_policy"
输出如下:
used_memory:33107888
used_memory_human:31.57M
maxmemory:120000000
maxmemory_human:114.44M
maxmemory_policy:noeviction
可以看到:
- 最大内存仅为 114 MB(对于现代 WordPress + 多插件环境来说明显偏小)。
- 淘汰策略为
noeviction(罪魁祸首)。
2. 查看服务器整体内存情况

free -h
结果:
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. 临时修复(立即生效,无需重启)
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。
vim /usr/local/redis/etc/redis.conf
找到或添加以下两行:

maxmemory 1024mb
maxmemory-policy allkeys-lru
保存后重启 Redis(OneinStack 的服务名是 redis-server):
service redis-server restart
3. 验证修改
redis-cli CONFIG GET maxmemory
# 输出:1073741824 (即 1GB)
redis-cli CONFIG GET maxmemory-policy
# 输出:allkeys-lru
五、最终结果
再次执行批量处理脚本:
php polylang-batch-zh-to-en-tags.php
输出:
🚀 开始批量处理所有zh标签,自动添加en翻译(分页模式)...
📊 正在处理第 1 - 1000 个标签...
📊 正在处理第 1001 - 2000 个标签...
...
🎉 全部处理完成!
📊 统计:
已处理新标签: 0
已跳过已有翻译: 8289
✅ 所有标签都已经处理完毕,和手动添加的完全一样!
不再有任何 Redis 错误,脚本顺利运行完成!
六、经验总结
- Redis 默认的
noeviction策略并不适合缓存场景,尤其是在有限内存环境下。推荐使用allkeys-lru或volatile-lru。 - WordPress + W3 Total Cache + Redis 对象缓存会大量消耗内存,务必根据服务器实际情况设置合理的
maxmemory。 - OneinStack 安装的 Redis 服务名是
redis-server,而不是常见的redis或redis.service,管理时需要注意。 - 批量操作触发大量缓存写入时,可以临时禁用对象缓存(
define('DONOTCACHEOBJECT', true);),但更好的做法是调整 Redis 策略让系统自动适应。
七、延伸建议
- 若网站流量增长,可将
maxmemory进一步提升至 1.5GB ~ 2GB(视总内存而定)。 - 定期监控 Redis 内存使用:
redis-cli --stat或集成redis_exporter+ Prometheus。 - W3 Total Cache 的对象缓存可适当缩短“垃圾回收间隔”(如 3600 秒),避免过期键堆积。
希望这篇博客能帮助到遇到类似问题的朋友。如果你们也有关于 Redis + WordPress 的踩坑经历,欢迎在评论区交流讨论!