Redis - RDB 内存快照:宕机后如何实现快速恢复
文章目录

引言
AOF 通过记录写命令保证数据不丢,但恢复时需要逐条回放,速度受限于文件大小。RDB(Redis Database)走了另一条路:在某个时间点把内存中的所有数据以二进制格式写成一个文件,恢复时直接加载到内存,速度比 AOF 快一个数量级。
RDB 的生成方式
Redis 提供两个命令生成 RDB 快照:
SAVE:主线程阻塞式生成
SAVE 命令让主线程直接执行快照生成,期间不处理任何客户端请求。对于大实例来说,这可能意味着几秒甚至几十秒的完全不可用。线上环境绝对不要用 SAVE。
BGSAVE:子进程后台生成
BGSAVE 是生产环境的标准做法。主进程 fork 出一个子进程,由子进程负责遍历内存、写入 RDB 文件,主进程继续正常服务。
fork 的关键在于 Linux 的写时复制(Copy-On-Write)机制:
- fork 瞬间,子进程和父进程共享同一块物理内存。
- 子进程开始读内存、写 RDB 文件。
- 如果父进程在此期间修改了某个内存页,操作系统才会真正复制那一页。

所以 BGSAVE 期间,内存开销取决于父进程的写入量。如果写入很少,几乎不额外占内存;如果写入密集,最坏情况下内存会接近翻倍。
快照的时间点问题
BGSAVE 生成的是 fork 那一刻的内存状态。fork 之后主进程继续接收写入,这些新写入不会出现在当前这份 RDB 里。也就是说,RDB 天然会丢失最后一次快照之后的所有写入。
快照频率越高,丢失的数据越少,但 fork 的开销也越大。这是一个需要根据业务容忍度来权衡的参数。
快照频率的配置
Redis 通过 save 配置项控制自动触发 BGSAVE 的条件:
save 900 1 # 900秒内至少1次写入
save 300 10 # 300秒内至少10次写入
save 60 10000 # 60秒内至少10000次写入
满足任一条件就触发。默认配置比较保守,生产环境需要根据写入量和可接受的数据丢失量来调整。
如果完全不需要 RDB,可以注释掉所有 save 行或设置 save ""。
RDB 文件的特点
RDB 是经过压缩的二进制文件,体积比 AOF 小很多。一个 10GB 内存的实例,RDB 文件可能只有 2-3GB。这带来几个好处:
- 恢复速度快:直接把二进制数据加载到内存,不需要解析和执行命令。
- 适合备份和传输:文件小,网络传输快,适合做异地备份。
- 主从全量同步用 RDB:从库第一次连接主库时,主库生成 RDB 发送过去。
fork 的性能影响
fork 是 BGSAVE 的性能瓶颈所在。虽然 fork 本身不复制物理内存,但需要复制页表(Page Table)。页表大小和实例使用的内存页数成正比:
- 4KB 页大小时,10GB 内存约有 260 万个页表项
- 复制这些页表项本身就需要几十毫秒
实测数据:
| 实例内存 | fork 耗时(参考值) |
|---|---|
| 1GB | 约 5ms |
| 10GB | 约 30-50ms |
| 25GB | 约 80-150ms |
这段时间主线程是完全阻塞的。所以大实例要特别注意 BGSAVE 的频率。
开启 Huge Pages(2MB 大页)可以减少页表项数量,但会让 COW 的粒度变大——修改一个字节就要复制 2MB,反而可能增加内存开销。Redis 官方建议关闭 Transparent Huge Pages(THP)。

增量快照的可能性
能不能只保存上次快照之后变化的数据?理论上可以,但 Redis 需要额外记录哪些 key 被修改过,这本身就有内存和 CPU 开销。对于修改频繁的场景,"增量"可能比"全量"还大。所以 Redis 没有走增量快照的路线。

混合持久化:AOF + RDB 的最佳组合
Redis 4.0 引入了混合持久化模式,通过配置开启:
aof-use-rdb-preamble yes
开启后,AOF 重写时不再用纯命令格式,而是:
- 文件前半段是 RDB 格式的全量数据(二进制,体积小)
- 文件后半段是重写期间新增的写命令(AOF 格式)

恢复时先加载 RDB 部分(快),再回放后面的命令(少),兼顾了恢复速度和数据完整性。
这是目前生产环境的推荐配置。
RDB 与 AOF 的对比
| 维度 | RDB | AOF |
|---|---|---|
| 文件格式 | 二进制压缩 | 文本命令 |
| 文件大小 | 小 | 大(重写前) |
| 恢复速度 | 快 | 慢 |
| 数据丢失 | 最后一次快照后的全部 | 取决于 fsync 策略 |
| 生成开销 | fork + 遍历内存 | 追加写(轻量) |
| 适用场景 | 备份、主从同步、快速恢复 | 数据安全性要求高 |
实践建议

- 同时开启 RDB 和 AOF,用混合持久化模式。RDB 负责快速恢复,AOF 负责减少数据丢失。
- 关闭 THP:
echo never > /sys/kernel/mm/transparent_hugepage/enabled,避免 COW 时内存暴涨。 - 监控 fork 耗时:通过
INFO persistence的latest_fork_usec字段观察。 - 大实例控制快照频率:25GB 以上的实例,BGSAVE 间隔不要太短。
- RDB 文件定期异地备份:RDB 文件天然适合做灾备,利用好这个特性。
- 主从架构下让从库做 BGSAVE:减轻主库的 fork 压力。
RDB 和 AOF 各有所长,混合持久化把两者的优势结合起来,是当前 Redis 持久化的最优解。理解了这两种机制的原理和代价,才能在"数据安全"和"性能开销"之间找到适合自己业务的平衡点。

更多推荐




所有评论(0)