2026年7月12日 · 6 分钟阅读

Redis 持久化:RDB、AOF 与混合持久化全解析

深入对比 Redis 两种持久化方式:RDB 的 COW 原理与触发时机、AOF 的写回策略与重写机制、Redis 7.0 Multi Part AOF,以及混合持久化如何兼得二者之长。

Redis 之所以被归为”缓存数据库”而不是”缓存”——就是因为它能在重启后恢复数据。这个能力来自它的持久化机制:RDBAOF

这篇文章聚焦底层原理,回答三个问题:数据是怎么写进磁盘的、什么时候写的、重启时怎么读回来。


RDB 持久化

RDB(Redis Database Backup)是全量快照,把某个时刻的所有内存数据写入磁盘。

触发方式

方式说明
save同步执行,阻塞主线程,不推荐生产环境使用
bgsavefork 子进程执行,不阻塞主线程,生产环境的默认选择
自动触发save 900 1(900 秒内至少 1 次写)等配置条件
主从复制首次同步slave 连接 master 时自动触发
关闭 Redisshutdown 时自动生成

Copy-On-Write(写时复制)

这是 RDB 中最关键的工程原理。bgsave 执行时:

  1. fork:主进程 fork 出一个子进程,子进程共享主进程的内存页。
  2. 子进程写 RDB:子进程遍历自己的内存页,写入临时文件。
  3. 主进程继续服务:主进程继续处理请求。
    • 读操作:直接读共享内存页,不影响子进程。
    • 写操作:操作系统会将被修改的共享内存页复制一份,主进程在自己的副本上写,子进程依然引用旧页。

所以 bgsave 期间如果有大量写操作,会导致 COW 触发频繁,内存开销上升(可达到原内存的 1 倍)。这也是为什么建议单机内存不要过大(比如 8G),否则 fork 时的内存抖动可能把机器干到 OOM。

优势与劣势

优势

  • 生成的是压缩二进制文件,体积小,适合备份和灾难恢复。
  • 恢复速度快——直接解析还原,不需要逐条执行命令。

劣势

  • 无法做到秒级持久化——生成快照是繁重操作,频繁执行会影响性能。
  • 有数据丢失风险——两次 RDB 之间的数据若宕机则全部丢失。
  • 旧版 RDB 可能不兼容新版 Redis。

AOF 持久化

AOF(Append Only File)是命令日志,每个写命令都会被追加到文件中。

工作流程

写命令 → 追加到 AOF 缓冲区 → write 写入内核缓冲区 → fsync 刷盘

整个流程分三步:

  1. 命令追加(Append):所有写命令追加到 server.aof_buf 缓冲区。
  2. 文件写入(write):调用 write 系统调用,将缓冲区数据写入内核缓冲区后立即返回(延迟写)。
  3. 文件同步(fsync):调用 fsync 系统调用,强制内核缓冲区数据同步到磁盘。

fsync 策略

策略行为数据安全性性能
always每个写命令都 fsync最安全,最多丢失 1 个命令最慢
everysec每秒 fsync 一次最多丢失 1 秒数据推荐,性能较好
no由操作系统决定(Linux 默认 30s)最多丢失 30 秒数据最快

生产推荐 everysec:兼顾数据安全和写入性能,最多丢一秒数据。

AOF 重写(Rewrite)

AOF 文件随着时间推移会越来越大,需要定期重写来压缩。

重写原理:不是对旧 AOF 文件进行操作,而是直接从当前数据库状态生成最小命令集

例如,一个 key 被 SET 了 1000 次,AOF 里就记录了 1000 条 SET 命令。重写时直接读当前值,只生成一条 SET。

重写流程:

  1. fork 子进程,子进程基于当前内存数据生成新的 AOF 文件。
  2. 重写期间,新写入的命令会被记录到 AOF 重写缓冲区
  3. 子进程重写完成后,把重写缓冲区的内容追加到新 AOF 文件末尾。
  4. 用新 AOF 文件替换旧文件。

在 Redis 7.0 之前,整个阶段的内存开销较高——所有增量数据都要在内存中保留,且写入磁盘两次。

Redis 7.0 Multi Part AOF

Redis 7.0 引入了 Multi Part AOF,彻底解决了 AOF 重写期间的资源消耗问题。

文件被分为三种类型:

类型说明
BASE基础 AOF,由重写产生,最多一个
INCR增量 AOF,重写开始时创建,可能有多个
HISTORY历史的 BASE 和 INCR,重写完成后自动删除

重写时不再攒一堆增量在内存里,而是直接写到独立的 INCR 文件。重写完成后将 BASE + INCR 合并,旧文件标记为 HISTORY 自动回收。磁盘写入次数和内存占用都大幅下降。


混合持久化(RDB + AOF)

RDB 恢复快但丢数据多,AOF 丢数据少但恢复慢(逐条执行命令)。Redis 4.0 引入了混合持久化

  • 开启方式:aof-use-rdb-preamble yes
  • AOF 重写时,直接把当前数据以 RDB 格式 写到 AOF 文件开头,之后才是增量 AOF 命令。
[AOF 文件结构]
[RDB 部分(当前全量数据)] [AOF 部分(重写后的增量命令)]

恢复时:

  1. 先加载开头的 RDB 数据——极快。
  2. 再执行后面的增量 AOF 命令——补齐丢失的部分。

优点:兼具 RDB 的快速恢复和 AOF 的低丢数据。

缺点:AOF 文件中的 RDB 部分是二进制压缩格式,不可读。


RDB 与 AOF 对比

对比维度RDBAOF混合持久化
文件内容压缩二进制快照明文写命令RDB + 增量 AOF
文件大小中等
恢复速度很快慢(逐条执行)较快
数据安全性丢失较多everysec 最多丢 1 秒同 AOF
实时性不可实时可接近实时可接近实时
可读性不可读可读部分可读
对性能影响fork + COW + 磁盘 IO写操作 + fsyncfork + COW + fsync

工程建议

1. 缓存场景不要开持久化

如果 Redis 只做纯缓存,丢了数据能从数据库回源,完全没必要开持久化——省掉 fork 和磁盘 IO 开销,性能和稳定性都好得多。

2. 数据重要则用混合持久化

设置 appendfsync everysec + aof-use-rdb-preamble yes。恢复时既快又稳。

3. 合理配置重写阈值

auto-aof-rewrite-percentage 100      # AOF 文件增长 100% 时触发重写
auto-aof-rewrite-min-size 64mb       # AOF 文件至少 64MB 才触发重写

避免频繁重写导致磁盘 IO 飙升。

4. 大内存机器要小心 fork 耗时

单实例内存超过 8G 后,fork 时间会明显变长(可能会超过 1 秒),导致主线程停顿。建议单实例 ≤ 8G。

5. 在 slave 上做定期备份

master 只负责读写,定期在 slave 上做 bgsave,用脚本把 RDB 文件拷贝到远端。这样既不影响主节点,又能保证有灾备。


总结

  • RDB 是”快照”,用 COW 做子进程写,恢复快,但丢数据多。
  • AOF 是”日志”,用 write + fsync 刷盘,丢数据少,但恢复慢。
  • 混合持久化把两者优势结合起来:重写时写 RDB + 增量 AOF,恢复时先加载 RDB 再回放 AOF。
  • 不同的数据安全要求选择不同的持久化策略,没有银弹,只有取舍。