背景
Redis 是一个开源的使用 ANSI C 语言编写、支持网络、可基于内存亦可持久化的日志型、Key-Value 数据库,并提供多种语言的 API。
据官方描述,在 Redis 的 Lua 脚本引擎的垃圾回收机制中存在 Use After Free 漏洞,经过身份验证的远程攻击者可通过构造特殊的 Lua 脚本触发,从而最终可能导致远程任意代码的执行等。
Redis is an open-source, ANSI C-based, network-enabled, in-memory and persistent log-based Key-Value database that provides APIs in multiple languages.
According to the official description, there is a Use After Free vulnerability in the garbage collection mechanism of Redis's Lua script engine. Unauthenticated remote attackers can trigger it by constructing a specific Lua script, which may eventually lead to the execution of arbitrary code remotely.
Affected Versions:
- Redis < 6.2.20
- Redis < 7.2.11
- Redis < 7.4.6
- Redis < 8.0.4
- Redis < 8.2.2
- Valkey < 8.1.4
官方已发布漏洞补丁及修复版本,请评估业务是否受影响后,升级至安全版本
The official has released the vulnerability patch and the fix version. Please assess whether your business is affected and then upgrade to the secure version.
修复建议
Repair suggestion
官方已发布新版本修复了该漏洞,请受影响的用户尽快升级到安全版本:
The official has released a new version which has fixed this vulnerability. Affected users are advised to upgrade to the secure version as soon as possible:
- Redis >= 6.2.20
- Redis >= 7.2.11
- Redis >= 7.4.6
- Redis >= 8.0.4
- Redis >= 8.2.2
- Valkey >= 8.1.4
Refer: https://github.com/redis/redis/releases
需求
将 docker-compose.yml
中的 Redis 镜像版本升级至 redis:6.2.20
,并以最小影响 方式完成操作。由于 Redis 是有状态服务(挂载了 /data/redis-dev/data:/data
),升级过程中需特别关注数据兼容性 与服务中断时间。
yaml
# @Author: johnny
version: '3.9'
services:
redis:
image: redis:6.2.20
ulimits:
nofile: 65535
container_name: redis-dev
restart: always
ports:
- 36379:6379
volumes:
- /data/redis-dev/data:/data:rw
environment:
- TZ=Asia/Shanghai
command: redis-server --masterauth shield --requirepass shield --port 6379
🖥️ 单机模式升级
✅ 前提确认
- 使用 Redis 持久化(RDB 或 AOF) ,数据存储于
/data/redis-dev/data
; - 从旧版本升级至
redis:6.2.20
属于小版本更新,Redis 官方保证向后兼容 (参考:Redis 升级策略); redis:6.2.20
为官方稳定镜像。
✅ 结论:支持原地升级,数据兼容性风险极低。
🔧 推荐操作步骤(最小影响)
步骤 1:【可选但推荐】备份 Redis 数据
bash
# 进入容器并触发 RDB 快照(确保数据落盘)
# 将 your_redis_password 替换为实际密码
docker exec redis-dev redis-cli -a your_redis_password BGSAVE
# 等待快照完成
sleep 5
# 备份整个数据目录
cp -r /data/redis-dev/data /data/redis-dev/data.bak_$(date +%Y%m%d)
💡 即使升级失败,也可快速回滚数据。
步骤 2:拉取新镜像
bash
docker pull redis:6.2.20
步骤 3:执行滚动升级
bash
# 停止并删除旧容器(数据卷保留)
docker-compose down
# 启动新容器(使用新镜像并挂载原数据卷)
docker-compose up -d
⏱️ 停机时间 ≈ 1~3 秒(容器启动耗时),客户端将短暂断连,Redis 数据无丢失。
步骤 4:验证服务状态
bash
# 检查容器运行状态
docker-compose ps
# 查看 Redis 日志,确认无报错
docker logs redis-dev
# 验证版本与数据
docker exec redis-dev redis-cli INFO SERVER | grep redis_version
docker exec redis-dev redis-cli DBSIZE
# 查看所有数据库键空间信息
docker exec redis-dev redis-cli -a shield --no-auth-warning INFO keyspace
🚫 避免的高风险操作
操作 | 风险 |
---|---|
直接执行 docker-compose up -d (未先执行 down ) |
可能因镜像缓存仍使用旧版本 |
手动执行 docker stop + docker run |
易遗漏端口、卷或 ulimit 配置 |
未备份直接升级 | 数据损坏时无法回退 |
🔄 回滚方案(如遇问题)
bash
# 1. 在 docker-compose.yml 中回退至旧镜像版本
# 2. 恢复数据目录(如新版本损坏数据)
rm -rf /data/redis-dev/data
cp -r /data/redis-dev/data.bak_20251021 /data/redis-dev/data
# 3. 重启服务
docker-compose down && docker-compose up -d
✅ 本方案的优势
优势 | 说明 |
---|---|
数据零丢失 | 持久化文件兼容,直接复用 |
停机时间短 | 仅容器重启时间(秒级) |
配置一致 | 通过 Compose 文件确保环境一致性 |
快速回滚 | 备份 + 可控镜像版本 |
💡 长期维护建议
- 使用语义化标签 :避免
latest
,采用6.2
或6.2.20
(✅ 已满足) - 监控升级过程 :配合健康检查(如
redis-cli PING
) - 定期测试备份恢复:确保备份有效性
- 考虑主从架构:未来支持无感升级(先升从节点,再切换)
📘 单机模式命令汇总
bash
# 检查键空间
docker exec redis-dev redis-cli -a shield --no-auth-warning INFO keyspace
# 备份数据
docker exec redis-dev redis-cli -a shield BGSAVE && sleep 10
cp -r /data/redis-dev/data /data/redis-dev/data.bak_$(date +%Y%m%d)
ll data/
ll data.bak_20251021/
# 拉取镜像并重启
docker pull redis:6.2.20
docker-compose down && docker-compose up -d
# 验证数据
docker exec redis-dev redis-cli -a shield --no-auth-warning INFO keyspace
🔁 主从模式升级
适用于 Redis 主从架构(Master-Slave) 的安全升级流程,假设两台主机分别运行 Master 与 Slave 实例,均通过 docker-compose
管理。
✅ 环境假设:
- Master:容器名
redis-master
,数据目录/data/redis-master/data
- Slave:容器名
redis-slave
,数据目录/data/redis-slave/data
- 密码:
shield
- 镜像已更新为
redis:6.2.20
(各主机docker-compose.yml
中)
🚀 升级流程(先 Slave,后 Master)
🔁 阶段 1:升级 Slave 节点
- 确认主从同步正常
bash
docker exec redis-slave redis-cli -a shield --no-auth-warning INFO replication
# 预期输出:role:slave, master_link_status:up, master_sync_in_progress:0
- 记录当前复制偏移量(用于回滚验证)
bash
SLAVE_OFFSET=$(docker exec redis-slave redis-cli -a shield --no-auth-warning INFO replication | grep slave_repl_offset | cut -d: -f2)
echo "Slave offset before upgrade: $SLAVE_OFFSET"
- 备份数据
bash
docker exec redis-slave redis-cli -a shield --no-auth-warning BGSAVE
sleep 10
cp -r /data/redis-slave/data /data/redis-slave/data.bak_$(date +%Y%m%d)
ls -lh /data/redis-slave/data*
- 升级 Slave 服务
bash
docker-compose up -d redis-slave
⚠️ 请勿使用
docker-compose down && up -d
,否则将影响所有服务。
- 验证升级结果
bash
# 检查版本
docker exec redis-slave redis-cli -a shield --no-auth-warning INFO SERVER | grep redis_version
# 检查主从同步
docker exec redis-slave redis-cli -a shield --no-auth-warning INFO replication
# 检查数据完整性
docker exec redis-slave redis-cli -a shield --no-auth-warning INFO keyspace
✅ 预期状态:
role:slave
,master_link_status:up
,数据量与升级前一致。
🔁 阶段 2:升级 Master 节点
- 确认 Slave 已正常同步(Master 仍为旧版)
bash
docker exec redis-slave redis-cli -a shield --no-auth-warning INFO replication
# 确保 master_link_status:up
- 备份 Master 数据
bash
docker exec redis-master redis-cli -a shield --no-auth-warning BGSAVE
sleep 10
cp -r /data/redis-master/data /data/redis-master/data.bak_$(date +%Y%m%d)
ls -lh /data/redis-master/data*
- 升级 Master 服务
bash
docker-compose up -d redis-master
- 验证主从同步与数据
bash
# 检查 Master 版本
docker exec redis-master redis-cli -a shield --no-auth-warning INFO SERVER | grep redis_version
# 检查 Master 角色
docker exec redis-master redis-cli -a shield --no-auth-warning INFO replication
# 预期:role:master, connected_slaves:1
# 检查 Slave 连接状态
docker exec redis-slave redis-cli -a shield --no-auth-warning INFO replication
# 预期:master_link_status:up
# 测试读写同步
docker exec redis-master redis-cli -a shield --no-auth-warning SET upgrade_test "ok"
docker exec redis-slave redis-cli -a shield --no-auth-warning GET upgrade_test
✅ 返回
"ok"
表示主从同步正常,升级成功。
🔄 主从模式回滚方案
前提 :已按上述步骤完成数据备份(
data.bak_YYYYMMDD
)
📌 回滚原则
- 如 Master 已升级,先回滚 Master;
- 再回滚 Slave;
- 恢复旧镜像版本。
🔁 回滚 Slave 节点(如升级失败)
- 停止服务
bash
docker-compose stop redis-slave
- 恢复数据
bash
rm -rf /data/redis-slave/data
cp -r /data/redis-slave/data.bak_20251021 /data/redis-slave/data
chown -R 999:999 /data/redis-slave/data # Redis 容器用户 UID 一般为 999
- 回退镜像版本
在 docker-compose.yml
中恢复旧版本:
yaml
services:
redis-slave:
image: redis:6.0.20 # 回退版本
- 重启服务
bash
docker-compose up -d redis-slave
- 验证状态
bash
docker exec redis-slave redis-cli -a shield --no-auth-warning INFO replication
🔁 回滚 Master 节点(如升级失败)
- 停止服务
bash
docker-compose stop redis-master
- 恢复数据
bash
rm -rf /data/redis-master/data
cp -r /data/redis-master/data.bak_20251021 /data/redis-master/data
chown -R 999:999 /data/redis-master/data
- 回退镜像版本
yaml
services:
redis-master:
image: redis:6.0.20 # 回退版本
- 重启服务
bash
docker-compose up -d redis-master
- 验证主从同步
bash
# Master
docker exec redis-master redis-cli -a shield --no-auth-warning INFO replication
# Slave
docker exec redis-slave redis-cli -a shield --no-auth-warning INFO replication
📋 主从升级注意事项
项目 | 说明 |
---|---|
数据目录路径 | 使用 docker inspect redis-slave 确认实际挂载路径 |
权限控制 | Redis 容器用户为 redis (UID 999),需确保备份目录权限正确 |
升级顺序 | 先 Slave,后 Master,避免双节点不可用 |
客户端配置 | 确保应用连接策略为 Master 写、Slave 读,升级期间避免写入失败 |
监控复制延迟 | 升级后持续关注 INFO replication 中的 offset 差距 |
✅ 主从升级成功标志
- ✅ 主从角色正确(Master:
role:master
,Slave:role:slave
) - ✅
master_link_status:up
- ✅
master_repl_offset
≈slave_repl_offset
- ✅ 客户端读写正常
- ✅
INFO keyspace
数据量与升级前一致
📘 主从模式命令汇总
升级 Slave 服务
bash
# 检查数据完整性
docker exec redis-slave redis-cli -a shield --no-auth-warning INFO keyspace
# 检查主从同步
docker exec redis-slave redis-cli -a shield INFO replication
# 检查复制偏移量与延迟
docker exec redis-slave redis-cli -a shield --no-auth-warning INFO replication | grep slave_repl_offset
docker exec redis-slave redis-cli -a shield --no-auth-warning INFO replication | grep master_sync_in_progress
# 检查版本
docker exec redis-slave redis-cli -a shield --no-auth-warning INFO SERVER | grep redis_version
# 备份数据
docker exec redis-slave redis-cli -a shield BGSAVE && sleep 10
cp -r /data/redis/data /data/redis/data.bak_$(date +%Y%m%d)
# 检查备份
ll data/
ll data.bak_20251021/
# 更新服务
docker-compose down && docker-compose up -d
升级 Master 服务
bash
# 检查数据完整性
docker exec redis-master redis-cli -a shield --no-auth-warning INFO keyspace
# 检查主从同步
docker exec redis-master redis-cli -a shield INFO replication
# 检查复制偏移量与延迟
docker exec redis-master redis-cli -a shield --no-auth-warning INFO replication | grep slave_repl_offset
docker exec redis-master redis-cli -a shield --no-auth-warning INFO replication | grep master_sync_in_progress
# 检查版本
docker exec redis-master redis-cli -a shield --no-auth-warning INFO SERVER | grep redis_version
# 备份数据
docker exec redis-master redis-cli -a shield BGSAVE && sleep 10
cp -r /data/redis/data /data/redis/data.bak_$(date +%Y%m%d)
# 检查备份
ll data/
ll data.bak_20251021/
# 升级服务
docker-compose down && docker-compose up -d
按照上述流程操作,Redis 单机或主从升级将实现安全、可控、可回滚,对业务影响最小。