持久化、备份与恢复
RDB 是时间点快照:文件紧凑、恢复快,但两次快照间的数据可能丢失。AOF 记录写命令:恢复点更近、文件较大,需要 rewrite。两者同时开启时 Redis 通常优先用 AOF 恢复。
本章不只介绍参数,还会完成一次“写入数据 → 生成备份 → 启动隔离恢复实例 → 验证数据”的完整实验。
1. 先理解 RPO 和 RTO
- RPO:故障后最多允许丢多少数据。例如
appendfsync everysec通常意味着可能丢失约 1 秒写入; - RTO:从故障发生到服务恢复最多允许多长时间。数据越大,加载 RDB/AOF 所需时间越长。
持久化参数必须从业务目标倒推,而不是看到别人使用 everysec 就直接复制。
save 900 1
save 300 10
appendonly yes
appendfsync everysec
auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb
aof-use-rdb-preamble yes
2. RDB 的生成过程
redis-cli info persistence
redis-cli bgsave
redis-cli info persistence | grep rdb_last_bgsave_status
BGSAVE 和 AOF rewrite 会 fork 子进程。写入越频繁,写时复制额外消耗的内存越多;磁盘不足或 fork 失败都会导致持久化失败。不要把人工 SAVE 用在生产主节点,它会阻塞服务。
检查 RDB 文件实际位置:
redis-cli CONFIG GET dir
redis-cli CONFIG GET dbfilename
docker compose exec redis ls -lh /data
rdb_last_bgsave_status:ok 只表示最近一次后台保存成功,不表示备份已经离开故障主机。
3. AOF、fsync 与 rewrite
redis-cli INFO persistence | grep -E 'aof_enabled|aof_current_size|aof_base_size|aof_last_bgrewrite_status'
redis-cli BGREWRITEAOF
Redis 7 的 AOF 通常存放在 appendonlydir 中,由 manifest、base 文件和增量文件组成。备份时不要只随意复制其中一个文件;应在一致的时间点保存完整目录,或优先以 RDB 作为离线备份格式。
appendfsync | 数据风险 | 性能特点 |
|---|---|---|
always | 最低 | 每次写都 fsync,延迟明显增加 |
everysec | 通常约 1 秒窗口 | 最常见折中 |
no | 由操作系统决定,窗口更大 | 吞吐较高,风险最高 |
4. 做一份可恢复的 RDB 备份
从副本或受控窗口的节点备份,备份后做校验和并上传到异地存储:
redis-cli bgsave
sudo install -d -m 0700 /backup/redis
sudo cp --reflink=auto /var/lib/redis/dump.rdb /backup/redis/dump-$(date +%F-%H%M%S).rdb
sha256sum /backup/redis/dump-*.rdb | tail -1
Docker 实验环境可以这样导出:
mkdir -p backup
redis-cli BGSAVE
docker compose cp redis:/data/dump.rdb ./backup/dump.rdb
sha256sum ./backup/dump.rdb
备份文件应包含实例、时间、Redis 版本和校验和元数据,并上传到不同故障域。只放在原 Redis 主机的 /backup 目录无法应对主机或磁盘损坏。
5. 在隔离容器完成恢复演练
先写入可识别的数据并生成新备份:
redis-cli SET recovery:user:42 'Alice'
redis-cli HSET recovery:order:1001 status paid amount 299
redis-cli BGSAVE
docker compose cp redis:/data/dump.rdb ./backup/recovery-test.rdb
创建独立数据卷并复制备份,不要覆盖正在运行的实例:
docker volume create redis-recovery-data
docker run --rm \
--volume redis-recovery-data:/restore \
--volume "$PWD/backup:/backup:ro" \
alpine:3.20 sh -c 'cp /backup/recovery-test.rdb /restore/dump.rdb'
docker run --detach \
--name redis-recovery \
--publish 127.0.0.1:6380:6379 \
--volume redis-recovery-data:/data \
redis:7.4-alpine
验证恢复实例:
redis-cli -p 6380 GET recovery:user:42
redis-cli -p 6380 HGETALL recovery:order:1001
redis-cli -p 6380 DBSIZE
docker logs redis-recovery
预期读到 Alice 和订单字段。验证后清理:
docker rm --force redis-recovery
docker volume rm redis-recovery-data
恢复 RDB:停止目标实例,备份现有数据目录,将 RDB 放到 dir 下并命名为 dbfilename 后启动。恢复 AOF 前必须复制原文件;redis-check-aof --fix 会截断损坏尾部,可能丢最后一段写入。
redis-check-rdb /backup/redis/dump-2026-01-01-010101.rdb
# 仅在副本上处理 AOF,且先复制原文件
redis-check-aof --fix /var/lib/redis/appendonlydir/appendonly.aof.1.incr.aof
“服务启动成功”不是恢复成功。隔离环境中验证 key 数量、抽样数据、TTL、应用读写和复制关系,再执行切流。恢复演练应周期化,并记录实际 RPO/RTO。
6. 生产备份检查清单
- 备份优先从副本生成,减少主节点 fork 与磁盘压力;
- 文件复制完成后计算校验和;
- 备份加密并保存到不同故障域;
- 设置保留周期和不可变/防误删策略;
- 定期在隔离环境恢复,而不是只检查文件存在;
- 记录恢复耗时、丢失窗口和验证结果;
- 故障时保留原始 RDB/AOF,修复工具只作用于副本。