在这里插入图片描述

引言

AOF 通过记录写命令保证数据不丢,但恢复时需要逐条回放,速度受限于文件大小。RDB(Redis Database)走了另一条路:在某个时间点把内存中的所有数据以二进制格式写成一个文件,恢复时直接加载到内存,速度比 AOF 快一个数量级。

RDB 的生成方式

Redis 提供两个命令生成 RDB 快照:

SAVE:主线程阻塞式生成

SAVE 命令让主线程直接执行快照生成,期间不处理任何客户端请求。对于大实例来说,这可能意味着几秒甚至几十秒的完全不可用。线上环境绝对不要用 SAVE

BGSAVE:子进程后台生成

BGSAVE 是生产环境的标准做法。主进程 fork 出一个子进程,由子进程负责遍历内存、写入 RDB 文件,主进程继续正常服务。

fork 的关键在于 Linux 的写时复制(Copy-On-Write)机制:

  1. fork 瞬间,子进程和父进程共享同一块物理内存。
  2. 子进程开始读内存、写 RDB 文件。
  3. 如果父进程在此期间修改了某个内存页,操作系统才会真正复制那一页。

在这里插入图片描述

所以 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 + 遍历内存 追加写(轻量)
适用场景 备份、主从同步、快速恢复 数据安全性要求高

实践建议

在这里插入图片描述

  1. 同时开启 RDB 和 AOF,用混合持久化模式。RDB 负责快速恢复,AOF 负责减少数据丢失。
  2. 关闭 THPecho never > /sys/kernel/mm/transparent_hugepage/enabled,避免 COW 时内存暴涨。
  3. 监控 fork 耗时:通过 INFO persistencelatest_fork_usec 字段观察。
  4. 大实例控制快照频率:25GB 以上的实例,BGSAVE 间隔不要太短。
  5. RDB 文件定期异地备份:RDB 文件天然适合做灾备,利用好这个特性。
  6. 主从架构下让从库做 BGSAVE:减轻主库的 fork 压力。

RDB 和 AOF 各有所长,混合持久化把两者的优势结合起来,是当前 Redis 持久化的最优解。理解了这两种机制的原理和代价,才能在"数据安全"和"性能开销"之间找到适合自己业务的平衡点。

在这里插入图片描述

Logo

汇聚全球AI编程工具,助力开发者即刻编程。

更多推荐