在完成 Nginx、OpenSSL 和 PHP 等组件升级后,我继续检查了这台阿里云 ECS 上的 Redis。
服务器使用 OneinStack 环境,Redis 并不是通过 RPM 安装,而是部署在:
/usr/local/redis
升级前运行的版本为:
Redis 7.0.11
这次我的目标并不是简单替换一个 redis-server 文件,而是尽量把升级前审计、数据备份、内核参数优化、旁路编译、兼容性验证、生产切换和回滚方案都做完整,最终将 Redis 升级到:
Redis 8.10.0
jemalloc 5.3.0
整个生产切换最终成功,WordPress 中文站、英文站和管理站均正常运行。
一、升级前的 Redis 环境
升级前,Redis 的主要情况如下:
- Redis 版本:7.0.11
- 运行模式:standalone
- 监听地址:127.0.0.1:6379
- 配置文件:
/usr/local/redis/etc/redis.conf - 数据目录:
/usr/local/redis/var - systemd 服务:
redis-server.service - 服务用户:
redis - 最大内存:1GB
- 淘汰策略:
allkeys-lru - AOF:未启用
- 定时 RDB:已关闭
- 已加载模块:无
- PHP Redis 扩展:6.3.0
- WordPress 缓存插件:W3 Total Cache
服务器总内存约为 3.6GiB,Redis 升级前已经使用约 880MiB 内存,缓存键数量约 30 万。
Redis 的缓存命中率很高,而且绝大多数键都设置了过期时间,说明它主要承担 WordPress 对象缓存和页面相关缓存,而不是保存不可丢失的业务数据。
不过,这并不意味着升级时可以直接清空 Redis。
如果一次性丢失 30 万个缓存键,WordPress、PHP-FPM 和远程 RDS 可能会在短时间内承受较大的缓存重建压力。因此,我仍然决定尽量保留现有缓存数据。
二、升级前发现的两个系统问题
在正式升级之前,我先检查了服务器的内核参数。
结果发现:
vm.overcommit_memory = 0
Redis 日志中也一直存在对应警告:
WARNING Memory overcommit must be enabled!
Redis 在执行 RDB 后台保存时需要通过 fork() 创建子进程。如果未启用内存过量分配,即使服务器还有可用内存,也可能因为内核的分配判断导致后台保存失败。
因此,我将其调整为:
vm.overcommit_memory = 1
并写入持久配置:
/etc/sysctl.d/99-redis-overcommit.conf
配置内容如下:
# Redis background saving and fork reliability
vm.overcommit_memory = 1
同时执行:
sysctl -w vm.overcommit_memory=1
Transparent Huge Pages 仍然开启
最初的 THP 状态为:
enabled: [always] madvise never
defrag: always defer defer+madvise [madvise] never
这表示 Transparent Huge Pages 仍然处于启用状态。
为了避免 Redis 在复制内存页、执行 RDB 保存或高频访问时产生额外延迟,我创建了一个 systemd 服务,在系统启动时自动关闭 THP。
最终状态变成:
always madvise [never]
always defer defer+madvise madvise [never]
至此,Redis 所需的两个重要系统参数均完成了调整:
vm.overcommit_memory = 1
Transparent Huge Pages = never
三、先生成一份最新的 RDB
升级前的 Redis 配置中包含:
save ""
appendonly no
也就是说:
- 定时 RDB 保存已经关闭;
- AOF 也没有启用。
当时磁盘上的 dump.rdb 还是 2026 年 6 月 5 日生成的,已经严重过期。
因此,在更换任何二进制文件之前,我先手动执行:
/usr/local/redis/bin/redis-cli BGSAVE
后台保存顺利完成:
Background saving started
RDB 后台保存成功
rdb_last_bgsave_status:ok
rdb_last_bgsave_time_sec:7
新的 RDB 文件约为:
263M
此次后台保存时,Redis 的 Fork Copy-on-Write 峰值只有约 6MB,说明保存过程对服务器内存造成的额外压力很小。
我随后备份了以下内容:
- Redis 7.0.11 所有二进制文件
redis.conf- 最新
dump.rdb - systemd 服务文件
- Redis Server、Memory、Persistence 和 Keyspace 信息
- 所有备份文件的 SHA-256
第一份完整备份目录为:
/root/redis-upgrade-backup-20260805-185250
备份总大小约为 334MB。
四、最初计划编译 Redis 8.10.0 全部内容
这次选择的目标版本为:
Redis 8.10.0
源码包下载完成后,文件信息如下:
文件大小:21550621 字节
SHA-256:f1baa4b28befd417aa6577ebeedde9e9fc7814cfcc299b2a6d2fd99ef7420a6c
源码包可以正常解压,顶层目录和版本信息也完全正确:
redis-8.10.0
#define REDIS_VERSION "8.10.0"
但在编译过程中,遇到了一个与 Redis 8 源码包结构有关的问题。
五、顶层 make 会同时编译多个附加模块
我最初尝试通过顶层 make 构建 Redis。
虽然 Redis 核心的 redis-server、redis-cli 和 redis-benchmark 都已经成功生成,但顶层构建还继续尝试编译:
- RedisBloom
- RediSearch
- RedisJSON
- RedisTimeSeries
随后出现了 Python 依赖错误:
ModuleNotFoundError: No module named 'dataclasses'
RedisTimeSeries 在链接阶段还出现了:
undefined reference to `main'
最终顶层 make 返回失败:
WARNING: The following module(s) failed to build:
redisbloom redisearch redisjson redistimeseries
ERROR: make build finished with module failure(s)
不过,日志同时明确显示:
Build complete.
redis-server: /root/redis-8.10.0/src/redis-server
也就是说,失败的是附加模块,而不是 Redis 核心。
六、为什么没有继续解决四个模块的编译问题
这台服务器上的 Redis 主要供 WordPress 和 W3 Total Cache 使用。
升级前执行:
MODULE LIST
结果为空。
WordPress 当前使用的是 Redis 的基础能力,例如:
- GET
- SET
- DEL
- EXPIRE
- Hash
- List
- Set
- Sorted Set
并不依赖以下命令:
FT.SEARCH
JSON.SET
TS.ADD
BF.ADD
因此,RedisBloom、RediSearch、RedisJSON 和 RedisTimeSeries 对当前网站并不是必需组件。
如果为了编译这四个模块,继续安装或升级 Python、Rust、CMake、LLVM 以及多个模块自己的依赖,不仅不会提升 WordPress 的缓存性能,还会显著增加服务器的维护复杂度。
最终我决定采用:
Redis 8.10.0 核心
不安装 RedisBloom
不安装 RediSearch
不安装 RedisJSON
不安装 RedisTimeSeries
这里的“一次到位”,并不等于把所有暂时用不到的功能全部安装,而是把当前真正需要的部分升级完整,并保证后续能够稳定维护。
七、只编译 Redis 核心目标
通过检查 src/Makefile,可以看到 Redis 核心提供了明确目标:
redis-server
redis-cli
redis-benchmark
redis-check-rdb
redis-check-aof
redis-sentinel
因此,我不再运行顶层 make,而是直接在 src 目录中构建需要的核心程序:
make -C src -j2 \
MALLOC=jemalloc \
DISABLE_WERRORS=yes \
redis-server \
redis-cli \
redis-benchmark
这次成功完成:
CC release.o
LINK redis-server
LINK redis-cli
LINK redis-benchmark
明确的核心目标检查成功
生成的版本为:
Redis server v=8.10.0
redis-cli 8.10.0
malloc=jemalloc-5.3.0
随后,我建立了一个独立旁路目录:
/root/redis-8.10.0-core-stage
目录中包含:
redis-server
redis-cli
redis-benchmark
redis-check-rdb -> redis-server
redis-check-aof -> redis-server
redis-sentinel -> redis-server
这样可以在不修改生产目录的情况下,对新版本进行完整测试。
八、使用 Redis 8.10.0 检查旧版 RDB
我使用新编译的 Redis 8.10.0 检查了 Redis 7.0.11 生成的 RDB:
/root/redis-8.10.0-core-stage/bin/redis-check-rdb \
/root/redis-upgrade-backup-20260805-185250/var/dump.rdb
检查结果为:
Checksum OK
RDB looks OK
303294 keys read
303242 expires
4364 already expired
这说明:
- RDB 文件结构正常;
- 校验和正常;
- Redis 8.10.0 可以识别 Redis 7.0.11 生成的数据;
- 文件中存在部分已经过期的缓存键,这属于正常现象。
九、先在 16379 端口测试 Redis 8.10.0
为了进一步降低风险,我没有直接替换生产服务,而是使用端口 16379 启动了一个临时 Redis 8.10.0 实例。
临时实例没有加载生产 RDB,也没有占用大量内存,只用于验证:
- 原有 Redis 配置是否能被 8.10.0 识别;
- Redis Server 能否正常启动;
- Redis CLI 能否读写;
- PHP Redis 扩展能否连接;
- systemd 和系统动态库是否存在兼容问题。
启动结果:
PONG
redis_version:8.10.0
redis_mode:standalone
tcp_port:16379
mem_allocator:jemalloc-5.3.0
Redis CLI 读写测试成功:
redis_cli_value=ok
PHP Redis 扩展测试也成功:
php_redis_value=ok
测试完成后,临时实例正常停止。
整个验证期间,生产 Redis 7.0.11 始终保持运行,没有停止,也没有替换二进制。
十、为什么 MODULE LIST 中出现了 vectorset
临时 Redis 8.10.0 启动后,MODULE LIST 并不是完全为空,而是出现了:
vectorset
这不是此前放弃编译的 RedisBloom、RediSearch、RedisJSON 或 RedisTimeSeries。
Vector Set 是与当前 Redis 8 核心程序一起构建的能力,因此最终方案更准确地说是:
Redis 8.10.0 核心
包含 Vector Set
不包含 RedisBloom
不包含 RediSearch
不包含 RedisJSON
不包含 RedisTimeSeries
它不会影响现有 WordPress 缓存,也不需要额外处理。
十一、正式切换前再次生成 RDB
在生产切换前,我再次执行了一次 BGSAVE。
此次保存耗时约 8 秒:
rdb_last_bgsave_status:ok
rdb_last_bgsave_time_sec:8
切换前 Redis 中共有:
302735 个键
随后创建了第二份、也是正式切换时使用的完整备份:
/root/redis-cutover-backup-20260805-193515
同时生成了独立回滚脚本:
/root/redis-rollback-20260805-193515.sh
回滚脚本可以完成:
- 停止当前 Redis;
- 恢复 Redis 7.0.11 二进制;
- 恢复旧配置;
- 恢复升级前 RDB;
- 恢复 systemd 服务;
- 启动 Redis 7.0.11;
- 检查版本和 PING。
只有在备份和回滚脚本都创建成功后,生产切换才正式开始。
十二、正式将 Redis 7.0.11 切换到 8.10.0
生产切换步骤为:
- 停止 Redis 7.0.11;
- 将旁路目录中的 Redis 8.10.0 二进制复制到
/usr/local/redis/bin; - 重建
redis-check-rdb、redis-check-aof和redis-sentinel链接; - 使用原有
redis.conf启动 Redis 8.10.0; - 等待 RDB 加载完成;
- 验证版本、键数量、内存、PHP 和 WordPress。
Redis 7.0.11 正常停止后,Redis 8.10.0 成功启动:
Redis 8.10.0 已开始响应
PONG
redis_version:8.10.0
redis_mode:standalone
tcp_port:6379
日志显示 Redis 8.10.0 成功读取了 Redis 7.0.11 生成的 RDB:
Loading RDB produced by version 7.0.11
RDB memory usage when created 881.41 Mb
Done loading RDB, keys loaded: 301533, keys expired: 1170
DB loaded from disk: 2.787 seconds
Ready to accept connections tcp
从停止 Redis 7 到 Redis 8 开始接受连接,实际中断时间非常短。
十三、升级后键数量为什么减少
切换前键数量为:
302735
切换后首次检查为:
301533
两者相差约 1200 个键。
这并不是升级导致的数据丢失。
Redis 日志已经明确记录:
keys expired: 1170
这些键在 RDB 加载时已经过期,因此不会再进入新实例。
此外,Redis 中的缓存键仍在持续到期和重新生成,后续再次检查时,键数量已经增长到:
301868
这说明 WordPress 和 W3 Total Cache 正在继续正常使用 Redis。
十四、WordPress 和 PHP 验证结果
Redis 8.10.0 启动后,我分别通过 Redis CLI 和 PHP Redis 扩展进行了读写测试。
结果如下:
redis_cli_value=ok
php_redis_value=ok
随后直接绕过 CDN,通过本机源站检查三个站点:
www.shuijingwanwq.com/wp-json/ 200
en.shuijingwanwq.com/wp-json/ 200
admin.shuijingwanwq.com/wp-login.php 200
这说明:
- 中文站正常;
- 英文站正常;
- 管理站正常;
- PHP Redis 扩展可以正常连接 Redis 8.10.0;
- W3 Total Cache 没有因为 Redis 升级而失效。
自动回滚最终没有被触发。
十五、升级后的内存与缓存情况
升级完成约 3 分钟后,Redis 内存状态为:
used_memory_human:872.55M
used_memory_rss_human:837.40M
maxmemory_human:1.00G
maxmemory_policy:allkeys-lru
mem_fragmentation_ratio:0.96
mem_allocator:jemalloc-5.3.0
统计信息为:
total_commands_processed:21184
rejected_connections:0
evicted_keys:0
keyspace_hits:162630
keyspace_misses:769
当时缓存命中率约为 99.5%。
虽然 872.55M 已经占到 1GB 限制的约 85%,但目前:
- 没有发生键淘汰;
- 没有拒绝连接;
- 命中率非常高;
- 服务器仍有约 2.1GiB 可用内存;
- Redis RSS 也低于
used_memory。
因此,我暂时没有立即提高 maxmemory。
当前继续保留:
maxmemory 1024mb
maxmemory-policy allkeys-lru
后续观察 24 至 72 小时。
只有出现以下情况时,才考虑将上限调整到:
1280mb
判断条件主要包括:
used_memory长时间接近 1GB;evicted_keys持续增长;keyspace_misses明显增加;- 缓存命中率出现持续下降。
对这台总内存只有 3.6GiB 的 WordPress 综合服务器来说,不适合直接将 Redis 提高到 1.5GB 或更高,还需要给 PHP-FPM、Nginx、系统缓存和 RDB 后台保存预留空间。
十六、两条日志提示是否需要处理
PID 文件提示
systemd 启动过程中出现:
Can't open PID file /var/run/redis/redis.pid (yet?)
但紧接着服务已经正常进入:
active (running)
Redis 主进程也被 systemd 正确识别。
这是 Type=forking 服务启动时,systemd 检查 PID 文件与 Redis 写入 PID 文件之间的短暂时序提示,不代表 Redis 启动失败。
暂时没有必要为了消除这一条提示,改造现有 systemd 服务模式。
未设置 Redis 密码
Redis 8.10.0 日志中还有:
WARNING: Redis does not require authentication.
Redis will accept connections from any local client.
当前 Redis 只监听:
127.0.0.1:6379
并且配置了:
protected-mode yes
Redis 只供同一台服务器上的 PHP 和 WordPress 使用。
如果现在新增密码,还需要同步修改 W3 Total Cache 和所有 Redis 客户端配置。因此,这条提示暂时不作为本次升级后的处理项目。
十七、最终升级结果
这次 Redis 升级的最终状态为:
Redis 7.0.11 → Redis 8.10.0:成功
jemalloc 5.3.0:正常
RDB 数据迁移:成功
30 万级缓存键加载:成功
RDB 加载时间:2.787 秒
Redis CLI 读写:成功
PHP Redis 扩展兼容:成功
WordPress 中文站:正常
WordPress 英文站:正常
WordPress 管理站:正常
vm.overcommit_memory:已调整为 1
Transparent Huge Pages:已关闭
自动回滚:未触发
升级后,Redis 服务保持:
active
enabled
PONG
十八、暂时保留升级文件
为了方便观察和回滚,我暂时保留以下文件:
/root/redis-upgrade-backup-20260805-185250
/root/redis-cutover-backup-20260805-193515
/root/redis-rollback-20260805-193515.sh
/root/redis-8.10.0
/root/redis-8.10.0-core-stage
/root/redis-8.10.0.tar.gz
其中最重要的是正式切换备份和回滚脚本:
/root/redis-cutover-backup-20260805-193515
/root/redis-rollback-20260805-193515.sh
这些文件至少保留 7 天。
确认 Redis 8.10.0 连续稳定运行后,再删除重复源码、临时测试目录和较早的备份。
总结
这次升级过程中,真正耗时的部分并不是 Redis 7 到 Redis 8 的数据兼容,而是 Redis 8.10.0 源码包默认构建流程中附带的多个扩展模块。
最终没有为了“全部编译成功”而继续安装一系列当前用不到的依赖,而是根据 WordPress 的真实需求,明确只编译和部署 Redis 核心。
通过旁路目录、RDB 检查、临时端口测试、PHP Redis 验证、最终 RDB 备份和自动回滚脚本,生产切换被控制在一个非常小的风险范围内。
最终结果也证明,这种方式更适合当前服务器:
- Redis 核心完成升级;
- WordPress 缓存数据得到保留;
- PHP 和 W3 Total Cache 保持兼容;
- 内核参数得到优化;
- 没有引入不必要的模块依赖;
- 整个切换过程没有触发回滚。
对于只将 Redis 用作 WordPress 对象缓存的服务器来说,稳定、可回滚、容易维护,比把所有扩展模块全部编译进去更重要。
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


发表回复