一、核心概念
在 Redis 故障恢复场景下,RDB 和 AOF 的主要区别体现在:
- 数据完整性:能恢复到哪个时间点的数据
- 恢复速度:从故障到服务可用的时间
- 恢复流程:Redis 如何选择持久化文件进行恢复
- 故障场景适应性:不同故障类型下的表现
二、故障恢复流程
1. Redis 启动时的恢复优先级
Redis 启动恢复流程:
┌─────────────────┐
│ Redis 启动 │
└────────┬────────┘
│
▼
检查 AOF 是否开启?
│
┌────┴────┐
是│ │否
│ │
▼ ▼
AOF 存在? RDB 存在?
│ │
是│ 是│
│ │
▼ ▼
加载 AOF 加载 RDB
│ │
└────┬────┘
▼
恢复完成
关键规则:
- AOF 优先级高于 RDB(如果
appendonly yes) - 只有 AOF 不存在或损坏时,才会使用 RDB
- 两者都不存在,Redis 以空数据启动
配置文件示例:
# 开启AOF后,优先使用AOF恢复
appendonly yes
appendfilename "appendonly.aof"
# RDB作为备份方案
save 900 1
dbfilename dump.rdb
dir /var/lib/redis
2. 不同持久化方式的恢复流程
RDB 恢复:
# 1. Redis启动,检测到 dump.rdb
# 2. 直接加载二进制数据到内存
# 3. 恢复完成,开始提供服务
redis-server /etc/redis/redis.conf
# [INFO] Loading RDB file...
# [INFO] RDB loaded in 2.5 seconds
# [INFO] Ready to accept connections
AOF 恢复:
# 1. Redis启动,检测到 appendonly.aof
# 2. 重新执行AOF文件中的每条命令
# 3. 恢复完成,开始提供服务
redis-server /etc/redis/redis.conf
# [INFO] Loading AOF file...
# [INFO] AOF loaded in 45 seconds
# [INFO] Ready to accept connections
三、故障恢复对比
1. 数据完整性(丢失数据量)
| 故障场景 | RDB 恢复 | AOF 恢复 |
|---|---|---|
| 正常关闭 | 丢失最后一次快照后的数据 | 丢失最后一次刷盘后的数据(最多1秒) |
| 进程崩溃 | 丢失最后一次快照后的数据 | 根据刷盘策略丢失0-1秒数据 |
| 机器宕机 | 丢失最后一次快照后的数据 | everysec:最多1秒;always:0丢失 |
| 磁盘损坏 | 取决于备份策略 | 取决于备份策略 |
示例场景:
场景 1:配置 save 900 1 + appendfsync everysec
时间轴:
00:00 - 上次RDB快照
00:10 - 发生大量写操作
00:15 - Redis进程崩溃
RDB恢复:丢失 00:00 - 00:15 的15分钟数据
AOF恢复:丢失 00:14:59 - 00:15:00 的1秒数据(最多)
场景 2:机器突然断电
RDB:丢失上次快照后的所有数据(可能几分钟到几小时)
AOF(always):无数据丢失(每次写都刷盘)
AOF(everysec):丢失最多1秒数据
AOF(no):丢失操作系统缓冲区数据(可能几十秒)
2. 恢复速度
实际测试数据(10GB Redis 实例):
| 持久化方式 | 文件大小 | 恢复时间 | 内存占用 |
|---|---|---|---|
| RDB | 2.5 GB | 3 分钟 | 10 GB |
| AOF(未重写) | 15 GB | 60 分钟 | 10 GB |
| AOF(重写后) | 3 GB | 25 分钟 | 10 GB |
| 混合持久化 | 3 GB | 5 分钟 | 10 GB |
速度差异原因:
// RDB恢复(直接加载)
void loadRDB() {
byte[] data = readFile("dump.rdb");
deserialize(data); // 直接反序列化到内存
// 时间复杂度:O(N),但常数项小
}
// AOF恢复(重新执行命令)
void loadAOF() {
String[] commands = readFile("appendonly.aof");
for (String cmd : commands) {
execute(cmd); // 逐条执行命令,涉及数据结构操作
}
// 时间复杂度:O(N*M),M是单条命令的时间复杂度
}
结论:
- RDB 恢复速度 ≈ AOF 恢复速度的 5-10 倍
- 数据量越大,RDB 优势越明显
3. 不同故障场景的适应性
场景 1:进程崩溃(OOM / Segmentation Fault)
RDB:
# 崩溃前的状态
18:00 - 最后一次BGSAVE完成
18:15 - 进程OOM崩溃
# 恢复结果
丢失 18:00 - 18:15 的15分钟数据
AOF:
# 崩溃前的状态
18:15:30.123 - 最后一次fsync成功
18:15:30.456 - 进程崩溃
# 恢复结果
丢失 18:15:30.123 - 18:15:30.456 的约0.3秒数据(everysec策略)
场景 2:AOF 文件损坏
检测与修复:
# 1. 启动时检测到AOF损坏
redis-server /etc/redis/redis.conf
# [ERROR] Bad file format reading AOF
# 2. 使用工具修复(截断损坏部分)
redis-check-aof --fix appendonly.aof
# [INFO] AOF file truncated, removed 1024 bytes
# 3. 重新启动
redis-server /etc/redis/redis.conf
# [INFO] AOF loaded successfully
RDB 作为备份:
# 如果AOF无法修复,切换到RDB恢复
mv appendonly.aof appendonly.aof.bak
redis-server /etc/redis/redis.conf
# [INFO] Loading RDB file (AOF disabled)
场景 3:误操作(FLUSHALL / FLUSHDB)
RDB:
- ❌ 如果误操作后触发了 BGSAVE,RDB 文件会保存空数据
- ✅ 如果有定期备份,可以恢复到备份时间点
AOF:
- ✅ AOF 文件记录了
FLUSHALL命令,可以手动编辑删除 - ✅ 如果 AOF 重写还未执行,可以快速恢复
恢复步骤:
# 1. 立即停止Redis(防止AOF重写)
redis-cli SHUTDOWN NOSAVE
# 2. 编辑AOF文件,删除FLUSHALL命令
vim appendonly.aof
# 找到并删除:
# *1
# $8
# FLUSHALL
# 3. 重启Redis
redis-server /etc/redis/redis.conf
4. 恢复过程中的可用性
RDB 恢复:
- ⏱️ 恢复时间短(分钟级)
- ⚠️ 恢复期间完全不可用
- ✅ 恢复完成后立即全量可用
AOF 恢复:
- ⏱️ 恢复时间长(可能几十分钟)
- ⚠️ 恢复期间完全不可用
- ⚠️ 大量命令重放对系统资源消耗大
高可用方案:
主从架构 + 哨兵:
┌─────────┐
│ 主节点 │ ← 宕机
└─────────┘
│
├─── 从节点1 ← 哨兵提升为新主节点(秒级切换)
│
└─── 从节点2 ← 同步新主节点
故障转移时间:< 30 秒
无需等待持久化恢复
四、生产环境最佳实践
1. 持久化配置策略
推荐配置(混合持久化):
# 开启AOF(数据安全)
appendonly yes
appendfsync everysec
# 开启RDB(快速备份)
save 900 1
save 300 10
save 60 10000
# 开启混合持久化(Redis 4.0+)
aof-use-rdb-preamble yes
# AOF重写配置
auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb
分层策略:
┌──────────────────────────┐
│ 实时数据安全:AOF │ ← 防止进程崩溃丢数据
├──────────────────────────┤
│ 快速恢复:RDB │ ← 定期生成,备份用
├──────────────────────────┤
│ 远程备份:定时RDB │ ← 防止机器/磁盘故障
└──────────────────────────┘
2. 备份与恢复流程
定期备份脚本:
#!/bin/bash
# redis_backup.sh
REDIS_CLI="/usr/bin/redis-cli"
BACKUP_DIR="/backup/redis"
DATE=$(date +%Y%m%d_%H%M%S)
# 触发BGSAVE
$REDIS_CLI BGSAVE
# 等待BGSAVE完成
while [ $($REDIS_CLI LASTSAVE) -eq $last_save ]; do
sleep 1
done
# 复制RDB文件
cp /var/lib/redis/dump.rdb $BACKUP_DIR/dump_$DATE.rdb
# 保留最近7天的备份
find $BACKUP_DIR -name "dump_*.rdb" -mtime +7 -delete
# 上传到远程存储(如OSS/S3)
aws s3 cp $BACKUP_DIR/dump_$DATE.rdb s3://redis-backup/
故障恢复SOP:
1. 评估故障类型
├─ 进程崩溃 → 自动重启(AOF恢复)
├─ 数据损坏 → 检查AOF → 修复/切换RDB
└─ 误操作 → 手动编辑AOF → 重启
2. 选择恢复文件
├─ AOF存在且完整 → 使用AOF(数据最新)
├─ AOF损坏 → 尝试修复(redis-check-aof --fix)
└─ 修复失败 → 使用最新RDB备份
3. 执行恢复
├─ 停止Redis
├─ 替换持久化文件
├─ 启动Redis
└─ 验证数据完整性
4. 切换流量(如果有主从)
├─ 从库恢复完成
├─ 数据同步追赶主库
└─ 哨兵/手动切换
3. 高可用架构下的持久化策略
主从复制 + 哨兵:
# 主节点:关闭持久化(提升性能)
appendonly no
save ""
# 从节点:开启持久化(数据安全)
appendonly yes
appendfsync everysec
aof-use-rdb-preamble yes
集群模式:
# 每个节点开启AOF
appendonly yes
appendfsync everysec
# 定期触发RDB备份(错峰执行)
# 节点1:每天凌晨1点
# 节点2:每天凌晨2点
# 节点3:每天凌晨3点
五、面试答题要点
简洁版:
Redis 故障恢复时,AOF 优先级高于 RDB。RDB 恢复快(分钟级)但可能丢失几分钟到几小时数据;AOF 恢复慢(可能几十分钟)但只丢失最多 1 秒数据(everysec 策略)。生产环境推荐开启混合持久化,结合两者优点:RDB 保证恢复速度,AOF 保证数据完整性。
详细版(回答结构):
- 恢复优先级:
- AOF 开启时优先用 AOF,AOF 损坏才用 RDB
- 数据完整性:
- RDB:可能丢失最后一次快照后的数据(分钟到小时级)
- AOF:根据刷盘策略,最多丢失 1 秒数据
- 恢复速度:
- RDB:快(直接加载二进制,GB 级数据几分钟)
- AOF:慢(重新执行命令,GB 级数据可能几十分钟)
- 故障场景适应性:
- 进程崩溃:AOF 数据更完整
- 误操作:AOF 可手动修复
- AOF 损坏:RDB 作为备份方案
- 生产建议:
- 开启混合持久化(Redis 4.0+)
- 定期备份 RDB 到远程
- 配合主从复制 + 哨兵实现高可用(秒级故障转移)