作为一名长期维护Redis服务的运维工程师,我深知版本升级过程中可能遇到的各种"坑"。最近我将生产环境的Redis从6.2.1升级到6.2.6版本,整个过程看似简单,但每个环节都需要谨慎操作。下面我会详细分享这次升级的全过程,包括那些官方文档没写的实用技巧。
在开始升级前,我首先确认了6.2.6版本与现有系统的兼容性。Redis的版本号遵循语义化版本控制(MAJOR.MINOR.PATCH),6.2.1到6.2.6属于小版本升级,理论上API完全兼容。但为保险起见,我还是查阅了Redis的发布说明,确认没有引入破坏性变更。
重要提示:生产环境升级前,务必在测试环境验证新版本与现有应用的兼容性。我曾遇到过某个PHP应用在Redis 6.2.4升级后出现连接问题,原因是客户端库对新协议的支持不完善。
升级过程需要编译安装,这对系统资源有一定要求。我执行了以下检查:
bash复制# 检查内存和交换空间
free -h
# 检查磁盘空间(至少需要200MB空闲空间)
df -h
对于资源紧张的服务器,建议在低峰期进行升级,并临时增加swap空间:
bash复制# 创建2GB的swap文件(如果内存不足)
sudo fallocate -l 2G /swapfile
sudo chmod 600 /swapfile
sudo mkswap /swapfile
sudo swapon /swapfile
Redis官方推荐通过源码编译安装,这能确保获得最佳性能。我选择直接使用wget下载:
bash复制wget http://download.redis.io/releases/redis-6.2.6.tar.gz
下载后验证文件完整性是个好习惯:
bash复制# 获取SHA256校验码(需到官网查看对应版本的校验值)
echo "5c7d25f1fe35d194e6f0d7f3e3e7791c55e4b9c3df3d5a5d6b9a3a3f3a3f3a3 redis-6.2.6.tar.gz" | sha256sum -c
直接kill进程可能导致数据丢失,正确做法是:
bash复制# 优雅关闭Redis(如果设置了密码需要添加-a参数)
redis-cli shutdown save
如果Redis无响应,再考虑强制停止:
bash复制# 查找Redis进程ID
ps -ef | grep redis-server | grep -v grep | awk '{print $2}' | xargs kill -9
根据持久化方式不同,备份策略也有所区别:
bash复制# 查找dump.rdb位置
redis-cli config get dir
# 创建备份目录
mkdir -p /backup/redis/$(date +%Y%m%d)
# 复制RDB文件
cp $(redis-cli config get dir | tail -n 1)/dump.rdb /backup/redis/$(date +%Y%m%d)/
bash复制# 确保AOF文件已同步
redis-cli bgrewriteaof
# 备份AOF文件
cp $(dirname $(redis-cli config get dir | tail -n 1))/appendonly.aof /backup/redis/$(date +%Y%m%d)/
实战经验:我曾遇到过备份时AOF文件不完整的情况。建议在备份前执行
redis-cli config set aof-rewrite-incremental-fsync yes确保数据完整性。
Redis 6.x需要GCC 9+版本,而CentOS 7默认安装的是GCC 4.8。以下是完整的GCC升级流程:
bash复制# 安装SCL仓库
yum install -y centos-release-scl
# 安装GCC 9
yum install -y devtoolset-9-gcc devtoolset-9-gcc-c++ devtoolset-9-binutils
# 临时启用GCC 9
scl enable devtoolset-9 bash
# 永久启用(建议仅在确认无误后执行)
echo "source /opt/rh/devtoolset-9/enable" >> ~/.bashrc
验证GCC版本:
bash复制gcc -v
# 应显示gcc version 9.3.1...
标准的make命令可以工作,但通过以下参数可以获得更好的性能:
bash复制make BUILD_TLS=yes USE_SYSTEMD=yes CFLAGS="-O2 -march=native"
各参数含义:
BUILD_TLS=yes:启用TLS支持USE_SYSTEMD=yes:集成systemd支持CFLAGS="-O2 -march=native":针对当前CPU架构优化编译完成后安装:
bash复制make install PREFIX=/usr/local/redis-6.2.6
注意:不要直接
make install,这会将文件分散到系统目录。指定PREFIX便于后续管理。
我建议保留旧版配置的同时,合并新版默认配置的优点:
bash复制# 生成配置差异
diff -u redis-6.2.1/redis.conf redis-6.2.6/redis.conf > redis.conf.diff
# 应用必要的新配置项
patch redis-6.2.1/redis.conf < redis.conf.diff
重点关注以下新配置项:
code复制# 6.2.6新增配置
io-threads 4 # 根据CPU核心数调整
aclfile /etc/redis/users.acl # 启用ACL
最佳实践是将数据文件与程序分离:
bash复制mkdir -p /data/redis/{data,logs,conf}
cp redis-6.2.1/redis.conf /data/redis/conf/
cp redis-6.2.1/dump.rdb /data/redis/data/
修改配置文件中的相关路径:
code复制dir /data/redis/data
logfile /data/redis/logs/redis.log
首次启动建议在前台运行,便于观察日志:
bash复制/usr/local/redis-6.2.6/bin/redis-server /data/redis/conf/redis.conf
确认服务正常后,再改为后台运行:
bash复制sed -i 's/daemonize no/daemonize yes/' /data/redis/conf/redis.conf
现代Linux系统推荐使用systemd管理:
bash复制cat > /etc/systemd/system/redis.service <<EOF
[Unit]
Description=Redis data structure server
After=network.target
[Service]
ExecStart=/usr/local/redis-6.2.6/bin/redis-server /data/redis/conf/redis.conf
ExecStop=/usr/local/redis-6.2.6/bin/redis-cli shutdown
Restart=always
User=redis
Group=redis
[Install]
WantedBy=multi-user.target
EOF
创建专用用户并设置权限:
bash复制useradd -r -s /sbin/nologin redis
chown -R redis:redis /data/redis
启动服务:
bash复制systemctl daemon-reload
systemctl enable --now redis
bash复制# 版本验证
redis-cli -v
# redis-cli 6.2.6
# 服务状态
redis-cli ping
# 应返回 PONG
# 数据完整性
redis-cli info keyspace
# 检查key数量是否与预期一致
使用redis-benchmark进行简单压测:
bash复制redis-benchmark -q -n 100000 -c 50 -P 10
重点关注:
Redis提供了丰富的监控数据:
bash复制watch -n 1 "redis-cli info | egrep 'used_memory|connected_clients|instantaneous_ops_per_sec'"
建议至少观察30分钟,确认内存使用、连接数、QPS等指标正常。
即使测试充分,生产环境仍需准备回滚方案:
停止新版Redis
bash复制systemctl stop redis
恢复旧版二进制文件
bash复制cp -r /usr/local/redis-6.2.1 /usr/local/redis
启动旧版服务
bash复制/usr/local/redis/bin/redis-server /data/redis/conf/redis.conf
如果新版已写入数据,回滚时可能需要:
bash复制# 将AOF文件转换为RDB格式(需要redis-check-aof工具)
redis-check-aof --fix appendonly.aof
问题1:fatal error: jemalloc/jemalloc.h: No such file or directory
解决方案:
bash复制make MALLOC=libc
问题2:server.c:xxxx:xx: error: ‘xxxxxxxx’ has no member named ‘xxxx’
这通常是GCC版本过低导致,确认已正确切换到GCC 9+。
问题:Can't handle RDB format version 10
这是因为新版Redis生成的RDB格式旧版无法识别。解决方法:
bash复制redis-cli --rdb dump.rdb
如果升级后性能下降,检查:
bash复制# 是否启用了THP(Transparent Huge Pages)
cat /sys/kernel/mm/transparent_hugepage/enabled
# 禁用THP
echo never > /sys/kernel/mm/transparent_hugepage/enabled
conf复制# 限制最大内存(根据服务器内存调整)
maxmemory 16gb
# 内存淘汰策略
maxmemory-policy allkeys-lru
# 开启内存碎片整理
activedefrag yes
conf复制# 启用ACL
aclfile /etc/redis/users.acl
# 重命名危险命令
rename-command FLUSHDB ""
rename-command CONFIG ""
# 启用TLS
tls-port 6379
tls-cert-file /etc/redis/redis.crt
tls-key-file /etc/redis/redis.key
配置Prometheus监控:
bash复制# 安装redis_exporter
wget https://github.com/oliver006/redis_exporter/releases/download/v1.45.0/redis_exporter-v1.45.0.linux-amd64.tar.gz
# 启动exporter
./redis_exporter -redis.addr localhost:6379 -web.listen-address :9121
Grafana仪表盘ID:763(官方Redis仪表盘)
每月执行内存碎片整理:
bash复制redis-cli memory purge
每季度检查AOF文件大小:
bash复制redis-cli bgrewriteaof
建议设置告警的指标:
Redis发布周期约为6个月一次稳定版。建议:
我个人的经验是,除非需要特定新功能或安全更新,否则生产环境不必追求最新版本。稳定性永远是第一考量。