Skip to content

Redis持久化机制详解

1. Redis 持久化在解决什么问题

Redis 的核心数据在内存中,进程重启或机器宕机后,内存数据会丢失。持久化的目标是把“可恢复的状态”落到磁盘,使 Redis 在重启后能把数据集恢复出来。

需要先把边界说清楚:

  • 持久化解决的是“单机重启可恢复”,不等价于高可用(HA)。高可用需要主从复制、哨兵或集群等机制来应对节点故障。
  • 持久化也不等价于“零数据丢失”。不同机制对应不同的数据丢失窗口与性能成本。

Redis 的主流持久化组合是:

  • RDB(快照):周期性把数据集做成一个紧凑的二进制快照。
  • AOF(追加日志):把写命令按 Redis 协议追加到文件,用重放命令恢复。
  • 混合持久化:在 AOF 重写时用 RDB 作为前导(preamble)提升恢复速度。

2. RDB(Redis Database)快照机制

2.1 触发方式:手动与自动

RDB 的核心命令是 SAVEBGSAVE

  • SAVE:在主线程直接生成 RDB,会阻塞 服务,一般不建议线上使用。
  • BGSAVE:fork 子进程生成 RDB,主线程继续处理请求,阻塞主要发生在 fork 瞬间。

自动触发由 redis.confsave 规则控制(满足“时间窗口 + 变更次数”就触发一次 BGSAVE):

save 900 1
save 300 10
save 60 10000

除了上述显式触发外,Redis 在某些流程中也可能触发生成 RDB(例如全量复制场景需要快照作为全量同步基础,具体取决于部署与配置)。

2.2 BGSAVE 的关键机制:fork + Copy-on-Write

BGSAVE 的主线是:

  1. 主进程 fork 出子进程。
  2. 子进程遍历内存数据结构,把数据序列化写入临时文件。
  3. 写完后原子替换(rename)到目标 dump.rdb,保证文件切换的原子性。

fork 后父子进程共享同一份物理内存页,操作系统通过写时复制(Copy-on-Write,COW)保证一致性:

  • 子进程只读旧数据并写文件。
  • 主进程继续处理写请求;当它要修改某个内存页时,该页会被复制出一个副本,主进程修改副本,子进程仍看到原页。

因此,RDB 对线上性能的主要影响来自两点:

  • fork 开销:数据集越大,fork 越慢,短暂停顿越明显。
  • COW 内存放大:BGSAVE 期间写入越多,被复制的页越多,内存峰值可能显著上涨

2.3 常用配置项与语义

配置项 作用 典型取舍
dir / dbfilename RDB 目录与文件名 落盘目录要有足够磁盘与写入性能
rdbcompression 是否压缩 RDB 省磁盘、增加 CPU
rdbchecksum 是否写入校验和 更安全、略增开销
stop-writes-on-bgsave-error RDB 失败时是否拒绝写入 保护数据一致性,但会影响可用性
rdb-save-incremental-fsync 增量 fsync 降低卡顿 更平滑,但写盘更频繁

2.4 优缺点与适用场景

优点:

  • 恢复快:加载一个二进制快照通常比重放大量命令快。
  • 文件紧凑:便于离线备份、跨机房传输与灾备演练。

缺点:

  • 数据丢失窗口大:快照间隔内的写入在宕机后会丢失。
  • fork 与 COW 成本:写入高峰期可能产生延迟尖刺与内存抖动。

适用场景:

  • 以缓存为主、允许丢失一段时间数据,且更看重恢复速度与备份便利性。

3. AOF(Append Only File)追加日志机制

3.1 AOF 记录的是什么:写命令的“重放日志”

开启 AOF 后,Redis 会在写命令执行完成后,把该命令按 Redis 协议(RESP)追加到 AOF 缓冲区,并按策略刷盘。重启恢复时,Redis 通过重放 AOF 中的写命令重建数据集。

3.2 写入链路:追加、写文件、fsync

AOF 相关的核心配置:

appendonly yes
appendfsync everysec

appendfsync 决定“刷到磁盘”的强度:

策略 fsync 时机 数据丢失窗口 性能影响
always 每条写命令都 fsync 最小 最大
everysec 每秒 fsync(典型默认) 约 1 秒级 折中
no 依赖 OS 自己刷盘 不可控 最好

注意:写入系统调用 write 只保证进入内核页缓存,不等价于真正落盘;fsync 才是把数据尽量推到磁盘的关键步骤。

3.3 AOF 为什么需要重写(rewrite)

AOF 的问题是“越写越大”,而且很多命令是可压缩的,例如:

  • INCR k 执行 100 次,最终状态只需要一条 SET k 100
  • 对同一个 hash field 多次 HSET,最终只需要保留最终值。

因此 Redis 提供 AOF 重写:把“恢复当前数据集所需的最小命令集合”生成到一个新文件,再用原子替换完成切换。

3.4 AOF 重写的底层流程:子进程生成基线 + 父进程追加增量

可以把 BGREWRITEAOF 的流程拆成三段理解:

  1. 主进程 fork 子进程:子进程基于当前内存数据生成“基线文件”(rewrite 文件),通常会用更紧凑的方式表达当前状态。
  2. 重写期间主进程仍在处理写请求:
    • 写命令继续追加到旧 AOF,保证现有 AOF 可用。
    • 同时写命令也会追加到“重写缓冲区”,用于之后把增量补到新文件。
  3. 子进程完成后,主进程进入短暂的切换窗口:
    • 把重写缓冲区的增量内容追加到新文件末尾。
    • 原子替换新旧文件,后续写入切到新 AOF。

这个设计的关键点是:重写不阻塞主线程的正常服务,但 fork 与最终切换阶段仍可能带来短暂抖动。

3.5 AOF 常用配置项与语义

配置项 作用 典型取舍
appendonly 是否开启 AOF 需要更高可靠性时开启
appendfsync fsync 策略 everysec 常用折中
auto-aof-rewrite-percentage 触发重写的增长比例 文件增大到一定倍数再重写
auto-aof-rewrite-min-size 触发重写的最小体积 避免小文件频繁重写
no-appendfsync-on-rewrite 重写期间是否跳过 fsync 降低抖动,但扩大丢失窗口
aof-rewrite-incremental-fsync 重写文件增量 fsync 平滑写盘,降低卡顿
aof-load-truncated AOF 末尾损坏时是否截断加载 提升可恢复性,但需评估一致性

3.6 AOF 的优缺点

优点:

  • 数据更完整everysec 下通常只丢 1 秒级数据,明显优于周期性快照。
  • 可解释性更强:AOF 本质是命令序列,便于用工具检查与修复(例如截断损坏尾部)。

缺点:

  • 文件通常更大,恢复速度可能慢(需要重放命令)。
  • fsync 与重写带来的磁盘 I/O 与延迟抖动需要关注。

4. 混合持久化:AOF 重写使用 RDB 前导

4.1 为什么需要混合持久化

纯 AOF 的恢复痛点在于:如果命令很多,重放会比较慢。混合持久化的思路是:在 AOF 重写生成新文件时,先把“当前全量数据”用 RDB 的二进制形式写在文件开头,再把重写期间的增量命令追加在后面。

恢复时:

  1. 先加载 RDB 前导,快速把全量数据恢复出来。
  2. 再重放尾部的增量 AOF,补齐最新写入。

4.2 配置与影响

混合持久化通常由 aof-use-rdb-preamble yes 控制。开启后带来的取舍:

  • 优点:AOF 恢复速度大幅提升(先 RDB,后少量增量命令)。
  • 缺点:AOF 文件开头是二进制 RDB,不再是纯文本命令序列,可读性下降,但这不影响 Redis 的加载。

5. 组合策略与启动优先级

5.1 可以同时开启 RDB 与 AOF

工程上常见做法是:同时开启 RDB 与 AOF(并推荐混合持久化),原因是:

  • AOF 提供更小的数据丢失窗口。
  • RDB 提供更快的冷启动恢复与更好的备份介质(单文件、紧凑)。

5.2 重启时加载哪个

当同时存在 RDB 与 AOF 时,Redis 通常优先加载 AOF(因为它更“新”)。因此你要保证:

  • AOF 文件可用(关注磁盘、权限、损坏修复策略)。
  • RDB 作为备份介质要定期验证可恢复性(不要只生成不校验)。

6. 运维排查与验证闭环

6.1 常用命令与检查项

INFO persistence
LASTSAVE
BGSAVE
BGREWRITEAOF
CONFIG GET save
CONFIG GET appendonly
CONFIG GET appendfsync

重点关注:

  • rdb_bgsave_in_progress / aof_rewrite_in_progress:是否有后台任务在跑。
  • rdb_last_bgsave_status / aof_last_bgrewrite_status:最近一次是否成功。
  • aof_current_sizeaof_base_size:AOF 增长与重写阈值是否合理。

6.2 修复工具(离线)

Redis 自带校验/修复工具:

redis-check-rdb dump.rdb
redis-check-aof --fix appendonly.aof

修复操作有破坏性风险,务必先备份原文件,并在隔离环境验证恢复结果。