一句话总结
RDB(快照):某个时刻的全量数据快照,二进制文件,恢复快但可能丢数据。通过 bgsave 子进程 + Copy-On-Write 实现不阻塞主进程。AOF(追加日志):记录每条写命令,数据安全但文件大恢复慢。混合持久化(Redis 4.0+):RDB 全量 + AOF 增量,兼顾恢复速度和数据安全。生产环境推荐混合持久化。
初级理解
RDB vs AOF 对比
| 对比维度 | RDB | AOF |
| 原理 | 全量快照 | 追加写命令 |
| 文件大小 | 小(二进制压缩) | 大(文本命令) |
| 恢复速度 | 快 | 慢(重放命令) |
| 数据安全 | 可能丢最后一次快照后的数据 | 最多丢 1 秒(everysec) |
| 对性能影响 | fork 子进程时短暂阻塞 | 持续写磁盘 IO |
| 默认开启 | ✅ 是 | ❌ 否 |
# RDB 触发方式
# 1. 自动触发(配置 save 规则)
save 900 1 # 900 秒内至少 1 次修改
save 300 10 # 300 秒内至少 10 次修改
save 60 10000 # 60 秒内至少 10000 次修改
# 2. 手动触发
SAVE # 阻塞主进程(不推荐)
BGSAVE # 子进程异步执行(推荐)
# AOF 配置
appendonly yes
appendfsync always # 每次写都刷盘(最安全,最慢)
appendfsync everysec # 每秒刷一次(推荐,最多丢 1 秒)
appendfsync no # 由 OS 决定(最快,最不安全)
一句话总结:RDB 全量快照恢复快但可能丢数据,AOF 增量日志数据安全但恢复慢。
中级深入
RDB — bgsave 与 Copy-On-Write
bgsave 通过 fork() 创建子进程,利用操作系统的 Copy-On-Write(写时复制)机制:
1. fork() 时,子进程共享父进程的内存页(只读)
2. 父进程继续处理写请求时,被修改的内存页会被复制一份
3. 子进程读取的是 fork 时刻的数据快照,不受后续修改影响
# bgsave 流程
# 1. Redis 主进程 fork() 子进程
# 2. 子进程遍历内存数据,写入临时 RDB 文件
# 3. 子进程完成后,用临时文件替换旧 RDB 文件
# 4. 主进程继续处理请求(Copy-On-Write 保证数据一致性)
# 注意:
# fork() 会阻塞主进程,阻塞时间取决于内存大小
# 10GB 内存约阻塞 100ms
# 所以 RDB 不适合频繁执行
AOF Rewrite — 压缩 AOF 文件
AOF 文件会越来越大,需要定期重写(Rewrite)来压缩。Rewrite 不是分析旧 AOF 文件,而是读取当前内存数据,生成等价的 SET 命令。
# AOF Rewrite 示例
# 原始 AOF:
SET count 1
INCR count # count=2
INCR count # count=3
INCR count # count=4
# Rewrite 后:
SET count 4 # 一条命令等价于上面 4 条
# 触发条件(自动)
auto-aof-rewrite-percentage 100 # AOF 文件增长 100%
auto-aof-rewrite-min-size 64mb # AOF 文件最小 64MB
# 手动触发
BGREWRITEAOF
混合持久化(Redis 4.0+)
AOF Rewrite 时,将当前内存数据以 RDB 格式写入 AOF 文件头部,后续增量以 AOF 格式追加。恢复时先加载 RDB 部分(快),再重放 AOF 部分(数据全)。
# 混合持久化配置
aof-use-rdb-preamble yes # Redis 5.0 默认开启
# 混合文件结构
# [RDB 二进制数据][AOF 增量命令]
# 恢复流程:
# 1. 加载 RDB 部分(快速恢复大部分数据)
# 2. 重放 AOF 部分(恢复增量数据)
# 兼顾 RDB 的恢复速度和 AOF 的数据安全
中级要点:bgsave 用 Copy-On-Write 不阻塞主进程;AOF Rewrite 压缩命令;混合持久化兼顾速度和安全。
高级拓展
持久化策略选择
| 场景 | 推荐方案 | 原因 |
| 纯缓存(可丢) | 不持久化 | 性能最优 |
| 数据不敏感 | RDB | 恢复快,可接受少量丢失 |
| 数据敏感 | AOF everysec | 最多丢 1 秒 |
| 生产推荐 | 混合持久化 | 恢复快 + 数据安全 |
持久化对性能的影响
# RDB 影响
# - fork() 阻塞:内存越大阻塞越久
# - Copy-On-Write 内存开销:写多时可能额外占用大量内存
# 建议:预留 50% 内存给 COW
# AOF 影响
# - always: 每次写都 fsync,性能最差
# - everysec: 每秒 fsync,性能影响小(推荐)
# - no: 不主动 fsync,性能最好但不安全
# 优化建议
# 1. 关闭 THP(Transparent Huge Pages)
# 2. 设置 no-appendfsync-on-rewrite yes(Rewrite 时不 fsync)
# 3. 合理设置 auto-aof-rewrite 参数
实战场景
场景:Redis 数据恢复
# 1. 确认持久化文件
ls -la /var/lib/redis/
# dump.rdb: RDB 文件
# appendonly.aof: AOF 文件
# 2. 检查文件完整性
redis-check-rdb dump.rdb
redis-check-aof --fix appendonly.aof
# 3. 恢复步骤
# 停止 Redis
systemctl stop redis
# 替换持久化文件
cp backup/dump.rdb /var/lib/redis/
# 启动 Redis(自动加载 RDB/AOF)
systemctl start redis
# 4. 验证数据
redis-cli DBSIZE
面试模拟
面试官:RDB 和 AOF 有什么区别?怎么选?
你:RDB 是全量快照,二进制文件小恢复快,但可能丢数据;AOF 是追加命令日志,数据安全但文件大恢复慢。生产环境推荐混合持久化(Redis 4.0+),AOF Rewrite 时将内存数据以 RDB 格式写入,兼顾恢复速度和数据安全。
面试官:bgsave 的原理是什么?
你:bgsave 通过 fork() 创建子进程,利用操作系统的 Copy-On-Write 机制。fork 时子进程共享父进程内存页(只读),父进程继续处理写请求时,被修改的内存页会被复制。子进程读取的是 fork 时刻的数据快照,不受后续修改影响。注意 fork 会短暂阻塞主进程,阻塞时间取决于内存大小。