After upgrading components like Nginx, OpenSSL, and PHP, I continued checking Redis on this Alibaba Cloud ECS.
The server uses the OneinStack environment, and Redis was not installed via RPM but deployed in:
/usr/local/redis
The version running before the upgrade was:
Redis 7.0.11
My goal this time was not simply to replace a redis-server file, but to complete the pre-upgrade audit, data backup, kernel parameter optimization, side-track compilation, compatibility verification, production cutover, and rollback plan as thoroughly as possible, ultimately upgrading Redis to:
Redis 8.10.0
jemalloc 5.3.0
The entire production cutover was ultimately successful, and the WordPress Chinese site, English site, and admin site all run normally.
1. Redis Environment Before Upgrade
Before the upgrade, the main details of the Redis setup were as follows:
- Redis version: 7.0.11
- Running mode: standalone
- Listening address: 127.0.0.1:6379
- Configuration file:
/usr/local/redis/etc/redis.conf - Data directory:
/usr/local/redis/var - systemd service:
redis-server.service - Service user:
redis - Maximum memory: 1GB
- Eviction policy:
allkeys-lru - AOF: Not enabled
- Scheduled RDB: Disabled
- Loaded modules: None
- PHP Redis extension: 6.3.0
- WordPress cache plugin: W3 Total Cache
The server has a total memory of about 3.6GiB. Before the Redis upgrade, it was using about 880MiB of memory, and the number of cache keys was around 300,000.
Redis has a very high cache hit rate, and the vast majority of keys have expiration times set, indicating that it primarily handles WordPress object cache and page-related caches, rather than storing irreplaceable business data.
However, this does not mean Redis can simply be emptied during the upgrade.
Losing 300,000 cache keys all at once would put significant cache rebuilding pressure on WordPress, PHP-FPM, and the remote RDS in a short period. Therefore, I still decided to preserve the existing cache data as much as possible.
2. Two System Issues Discovered Before Upgrade
Before the formal upgrade, I first checked the server’s kernel parameters.
I found that:
vm.overcommit_memory = 0
The corresponding warning had also been persistently present in the Redis logs:
WARNING Memory overcommit must be enabled!
Redis needs to create a child process via fork() when performing an RDB background save. If memory overcommit is not enabled, the background save may fail due to the kernel’s allocation checks, even if the server has available memory.
Therefore, I adjusted it to:
vm.overcommit_memory = 1
And wrote the persistent configuration to:
/etc/sysctl.d/99-redis-overcommit.conf
The configuration content is as follows:
# Redis background saving and fork reliability
vm.overcommit_memory = 1
Simultaneously, I executed:
sysctl -w vm.overcommit_memory=1
Transparent Huge Pages Still Enabled
The initial THP status was:
enabled: [always] madvise never
defrag: always defer defer+madvise [madvise] never
This indicates that Transparent Huge Pages were still enabled.
To prevent Redis from incurring additional latency when copying memory pages, performing RDB saves, or handling high-frequency access, I created a systemd service to automatically disable THP at system startup.
The final status became:
always madvise [never]
always defer defer+madvise madvise [never]
At this point, both important system parameters required by Redis had been adjusted:
vm.overcommit_memory = 1
Transparent Huge Pages = never
3. Generate a Latest RDB First
The Redis configuration before the upgrade included:
save ""
appendonly no
This means:
- Scheduled RDB saves were disabled;
- AOF was also not enabled.
The dump.rdb on disk at that time was still generated on June 5, 2026, and was severely outdated.
Therefore, before replacing any binary files, I manually executed:
/usr/local/redis/bin/redis-cli BGSAVE
The background save completed successfully:
Background saving started
RDB 后台保存成功
rdb_last_bgsave_status:ok
rdb_last_bgsave_time_sec:7
The new RDB file was approximately:
263M
During this background save, Redis’s Fork Copy-on-Write peak was only about 6MB, indicating that the save process put very little additional memory pressure on the server.
I subsequently backed up the following:
- All Redis 7.0.11 binary files
redis.conf- Latest
dump.rdb - systemd service file
- Redis Server, Memory, Persistence, and Keyspace information
- SHA-256 of all backup files
The first complete backup directory was:
/root/redis-upgrade-backup-20260805-185250
The total backup size was about 334MB.
4. Initial Plan to Compile Everything in Redis 8.10.0
The target version selected this time was:
Redis 8.10.0
After downloading the source package, the file information was as follows:
文件大小:21550621 字节
SHA-256:f1baa4b28befd417aa6577ebeedde9e9fc7814cfcc299b2a6d2fd99ef7420a6c
The source package extracted normally, and the top-level directory and version information were completely correct:
redis-8.10.0
#define REDIS_VERSION "8.10.0"
However, during the compilation process, I encountered an issue related to the source package structure of Redis 8.
5. Top-Level Make Simultaneously Compiles Multiple Additional Modules
I initially tried to build Redis using the top-level make.
Although the Redis core redis-server, redis-cli, and redis-benchmark were all successfully generated, the top-level build also continued to try to compile:
- RedisBloom
- RediSearch
- RedisJSON
- RedisTimeSeries
Subsequently, a Python dependency error occurred:
ModuleNotFoundError: No module named 'dataclasses'
RedisTimeSeries also showed the following during the linking phase:
undefined reference to `main'
Ultimately, the top-level make returned a failure:
WARNING: The following module(s) failed to build:
redisbloom redisearch redisjson redistimeseries
ERROR: make build finished with module failure(s)
However, the logs also clearly showed:
Build complete.
redis-server: /root/redis-8.10.0/src/redis-server
In other words, the failures were in the additional modules, not the Redis core.
6. Why I Did Not Continue Solving the Compilation Issues for the Four Modules
Redis on this server is primarily used by WordPress and W3 Total Cache.
Before the upgrade, I executed:
MODULE LIST
The result was empty.
WordPress currently uses Redis’s basic capabilities, such as:
- GET
- SET
- DEL
- EXPIRE
- Hash
- List
- Set
- Sorted Set
It does not rely on the following commands:
FT.SEARCH
JSON.SET
TS.ADD
BF.ADD
Therefore, RedisBloom, RediSearch, RedisJSON, and RedisTimeSeries are not essential components for the current website.
If I were to continue installing or upgrading Python, Rust, CMake, LLVM, and the various dependencies of these modules just to compile them, it would not improve WordPress’s cache performance. Instead, it would significantly increase the server’s maintenance complexity.
Ultimately, I decided to adopt:
Redis 8.10.0 核心
不安装 RedisBloom
不安装 RediSearch
不安装 RedisJSON
不安装 RedisTimeSeries
Here, “doing it right in one go” does not mean installing every feature that might temporarily be unused. It means completely upgrading the parts currently needed and ensuring stable maintainability going forward.
7. Compiling Only the Redis Core Targets
By checking src/Makefile, I could see that the Redis core provides specific targets:
redis-server
redis-cli
redis-benchmark
redis-check-rdb
redis-check-aof
redis-sentinel
Therefore, instead of running the top-level make, I directly built the required core programs in the src directory:
make -C src -j2 \
MALLOC=jemalloc \
DISABLE_WERRORS=yes \
redis-server \
redis-cli \
redis-benchmark
This completed successfully:
CC release.o
LINK redis-server
LINK redis-cli
LINK redis-benchmark
明确的核心目标检查成功
The generated versions were:
Redis server v=8.10.0
redis-cli 8.10.0
malloc=jemalloc-5.3.0
Next, I created an independent side-track directory:
/root/redis-8.10.0-core-stage
The directory contains:
redis-server
redis-cli
redis-benchmark
redis-check-rdb -> redis-server
redis-check-aof -> redis-server
redis-sentinel -> redis-server
This allows for complete testing of the new version without modifying the production directory.
8. Checking the Legacy RDB with Redis 8.10.0
I used the newly compiled Redis 8.10.0 to check the RDB generated by Redis 7.0.11:
/root/redis-8.10.0-core-stage/bin/redis-check-rdb \
/root/redis-upgrade-backup-20260805-185250/var/dump.rdb
The check results were:
Checksum OK
RDB looks OK
303294 keys read
303242 expires
4364 already expired
This indicates that:
- The RDB file structure is normal;
- The checksum is normal;
- Redis 8.10.0 can read the data generated by Redis 7.0.11;
- Some expired cache keys exist in the file, which is normal.
9. Testing Redis 8.10.0 on Port 16379 First
To further reduce risk, I did not directly replace the production service. Instead, I started a temporary Redis 8.10.0 instance using port 16379.
The temporary instance did not load the production RDB and did not consume a large amount of memory; it was solely used to verify:
- Whether the original Redis configuration could be read by 8.10.0;
- Whether the Redis Server could start normally;
- Whether the Redis CLI could read and write;
- Whether the PHP Redis extension could connect;
- Whether there were compatibility issues with systemd and system dynamic libraries.
The startup results were:
PONG
redis_version:8.10.0
redis_mode:standalone
tcp_port:16379
mem_allocator:jemalloc-5.3.0
The Redis CLI read/write test was successful:
redis_cli_value=ok
The PHP Redis extension test was also successful:
php_redis_value=ok
After testing, the temporary instance stopped normally.
Throughout the verification period, the production Redis 7.0.11 kept running without interruption, and no binaries were replaced.
10. Why vectorset Appeared in MODULE LIST
After the temporary Redis 8.10.0 started, MODULE LIST was not completely empty; instead, the following appeared:
vectorset
This is not RedisBloom, RediSearch, RedisJSON, or RedisTimeSeries, which were previously dropped from compilation.
Vector Set is a capability built alongside the current Redis 8 core program, so the final solution is more accurately described as:
Redis 8.10.0 核心
包含 Vector Set
不包含 RedisBloom
不包含 RediSearch
不包含 RedisJSON
不包含 RedisTimeSeries
It does not affect the existing WordPress cache and requires no additional handling.
11. Generating an RDB Again Before the Formal Cutover
Before the production cutover, I executed BGSAVE once more.
This save took about 8 seconds:
rdb_last_bgsave_status:ok
rdb_last_bgsave_time_sec:8
Before the cutover, Redis contained:
302735 个键
I then created the second complete backup, which was the one used for the formal cutover:
/root/redis-cutover-backup-20260805-193515
Simultaneously, I generated an independent rollback script:
/root/redis-rollback-20260805-193515.sh
The rollback script can accomplish the following:
- Stop the current Redis;
- Restore the Redis 7.0.11 binaries;
- Restore the old configuration;
- Restore the pre-upgrade RDB;
- Restore the systemd service;
- Start Redis 7.0.11;
- Check the version and PING.
Only after both the backup and rollback script were successfully created did the production cutover officially begin.
12. Formally Switching Redis 7.0.11 to 8.10.0
The production cutover steps were:
- Stop Redis 7.0.11;
- Copy the Redis 8.10.0 binaries from the side-track directory to
/usr/local/redis/bin; - Rebuild the
redis-check-rdb,redis-check-aof, andredis-sentinellinks; - Start Redis 8.10.0 using the original
redis.conf; - Wait for the RDB load to complete;
- Verify the version, key count, memory, PHP, and WordPress.
After Redis 7.0.11 stopped normally, Redis 8.10.0 started successfully:
Redis 8.10.0 已开始响应
PONG
redis_version:8.10.0
redis_mode:standalone
tcp_port:6379
The logs showed that Redis 8.10.0 successfully read the RDB generated by Redis 7.0.11:
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
The actual downtime from stopping Redis 7 to Redis 8 accepting connections was very short.
13. Why the Key Count Decreased After the Upgrade
The key count before the cutover was:
302735
The first check after the cutover was:
301533
The difference between the two was about 1,200 keys.
This was not data loss caused by the upgrade.
The Redis logs clearly recorded:
keys expired: 1170
These keys had already expired during the RDB load, so they did not enter the new instance.
Additionally, cache keys in Redis continue to expire and regenerate. When I checked again later, the key count had already grown to:
301868
This shows that WordPress and W3 Total Cache are continuing to use Redis normally.
14. WordPress and PHP Verification Results
After Redis 8.10.0 started, I performed read/write tests via the Redis CLI and the PHP Redis extension, respectively.
The results were as follows:
redis_cli_value=ok
php_redis_value=ok
I then bypassed the CDN and checked the three sites directly via the local origin server:
www.shuijingwanwq.com/wp-json/ 200
en.shuijingwanwq.com/wp-json/ 200
admin.shuijingwanwq.com/wp-login.php 200
This indicates that:
- The Chinese site is normal;
- The English site is normal;
- The admin site is normal;
- The PHP Redis extension can connect to Redis 8.10.0 normally;
- W3 Total Cache did not fail due to the Redis upgrade.
The automatic rollback was ultimately not triggered.
15. Memory and Cache Status After Upgrade
About 3 minutes after the upgrade was completed, the Redis memory status was:
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
The statistics were:
total_commands_processed:21184
rejected_connections:0
evicted_keys:0
keyspace_hits:162630
keyspace_misses:769
The cache hit rate at that time was about 99.5%.
Although 872.55M had already reached about 85% of the 1GB limit, currently:
- No keys have been evicted;
- No connections have been rejected;
- The hit rate is very high;
- The server still has about 2.1GiB of available memory;
- Redis RSS is also lower than
used_memory.
Therefore, I did not immediately increase maxmemory for the time being.
Currently, I continue to retain:
maxmemory 1024mb
maxmemory-policy allkeys-lru
I will observe it for 24 to 72 hours.
Only if the following situations occur will I consider adjusting the limit to:
1280mb
The judgment conditions mainly include:
used_memorystays close to 1GB for a long time;evicted_keyscontinues to grow;keyspace_missesincreases significantly;- The cache hit rate shows a continuous decline.
For this comprehensive WordPress server with only 3.6GiB of total memory, it is not appropriate to directly increase Redis to 1.5GB or higher; space must also be reserved for PHP-FPM, Nginx, system cache, and RDB background saves.
16. Whether Two Log Messages Need Handling
PID File Message
During the systemd startup process, the following appeared:
Can't open PID file /var/run/redis/redis.pid (yet?)
But immediately after, the service had already normally entered:
active (running)
The Redis main process was also correctly identified by systemd.
This is a brief timing message between systemd checking the PID file and Redis writing the PID file when the Type=forking service starts; it does not mean Redis failed to start.
For now, there is no need to modify the existing systemd service model just to eliminate this message.
Redis Password Not Set
The Redis 8.10.0 logs also contained:
WARNING: Redis does not require authentication.
Redis will accept connections from any local client.
Currently, Redis only listens on:
127.0.0.1:6379
And is configured with:
protected-mode yes
Redis is only used by PHP and WordPress on the same server.
If I add a password now, I would also need to synchronously update W3 Total Cache and all Redis client configurations. Therefore, this message is temporarily not an item to be handled after this upgrade.
17. Final Upgrade Results
The final status of this Redis upgrade was:
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:已关闭
自动回滚:未触发
After the upgrade, the Redis service maintained:
active
enabled
PONG
18. Temporarily Retaining Upgrade Files
To facilitate observation and rollback, I temporarily retained the following files:
/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
The most important among these are the formal cutover backup and the rollback script:
/root/redis-cutover-backup-20260805-193515
/root/redis-rollback-20260805-193515.sh
These files will be kept for at least 7 days.
After confirming that Redis 8.10.0 runs stably continuously, I will delete the duplicate source code, temporary test directory, and earlier backups.
Summary
During this upgrade process, the truly time-consuming part was not the data compatibility between Redis 7 and Redis 8, but the multiple extension modules included in the default build process of the Redis 8.10.0 source package.
Ultimately, rather than continuing to install a series of currently unused dependencies just to achieve a “fully successful compilation,” I chose to compile and deploy only the Redis core based on the actual needs of WordPress.
Through a side-track directory, RDB checks, temporary port testing, PHP Redis verification, a final RDB backup, and an automatic rollback script, the production cutover was controlled within a very small risk margin.
The final result also proves that this approach is more suitable for the current server:
- The Redis core was upgraded;
- WordPress cache data was preserved;
- PHP and W3 Total Cache remained compatible;
- Kernel parameters were optimized;
- No unnecessary module dependencies were introduced;
- The entire cutover process did not trigger a rollback.
For a server that only uses Redis as a WordPress object cache, stability, rollback capability, and ease of maintenance are more important than compiling all extension modules.

