Redis 从零到一(02):持久化机制 RDB 与 AOF
2026-10-12 09:40:00

适合人群:用过 Redis 当缓存,但没想过”断电之后数据怎么办”的同学。
本篇基于 Redis 7.x(AOF 的多文件机制以 7.0 为准),配置可直接复制。

一、内存很快,但断电就没了

Redis 的全部数据都在内存里,这意味着:进程一挂、机器一断电,数据全没。

对纯缓存场景,丢了可以回源重建,问题不大。但如果 Redis 里存的是计数器、分布式锁、延迟队列、购物车——丢了就是业务事故。所以 Redis 需要持久化:在”内存性能”和”数据安全”之间做权衡,把内存数据设法落到磁盘。

Redis 给出两套方案,思路完全不同:

  • RDB:定时拍快照——某一时刻内存数据的完整照片,二进制压缩存盘
  • AOF:记日志——把每一条写命令追加到文件,重启时重新执行一遍

图1:RDB、AOF 与混合持久化的工作方式

二、RDB:定时拍照

怎么触发

1
2
3
4
5
6
7
8
# 手动触发(生产慎用 SAVE:阻塞主线程)
SAVE # 前台拍照,期间所有命令排队等待
BGSAVE # 后台拍照,fork 子进程去做,主线程继续服务

# 配置自动触发:900 秒内至少 1 次修改 / 300 秒内 10 次 / 60 秒内 10000 次
save 900 1
save 300 10
save 60 10000

核心:fork + 写时复制(COW)

BGSAVE 时 Redis 会 fork() 出一个子进程去生成 RDB 文件。问题来了:拍照要遍历全量数据,期间主线程还在接写命令,子进程怎么拍出一份”一致性”的快照?

答案是操作系统的写时复制(Copy-On-Write):

  1. fork 出的子进程和父进程共享同一份物理内存页(只读)
  2. 子进程安心遍历内存生成 RDB 文件
  3. 父进程继续处理写命令——一旦要修改某个内存页,内核才把那一页复制一份给父进程改
  4. 结果:子进程看到的永远是 fork 那一瞬间”冻结”的数据版本

这是面试高频考点:BGSAVE 期间 Redis 会不会卡? fork 本身很快(复制的是页表不是内存),但数据量很大时页表复制也有几十到几百毫秒的停顿;之后主线程不受影响,代价只是写命令会多一次页复制。

RDB 的优缺点

优点:文件紧凑(压缩二进制)、恢复极快(直接载入)、适合容灾备份(一个文件拷走就行)。

缺点:两次快照之间的数据会丢。比如 save 300 10,最坏丢整整 5 分钟数据;fork 在大内存实例上开销不小。

三、AOF:把每条写命令记下来

三种刷盘策略

AOF 的流程是:写命令先进入 aof_buf 缓冲区,再由 appendfsync 决定多久真正写到磁盘:

1
2
3
4
5
6
appendonly yes

# 三档策略,性能与安全的滑杆
appendfsync always # 每条命令都 fsync:最多丢 1 条命令,慢
appendfsync everysec # 每秒一次:最多丢 1 秒数据,推荐(默认)
appendfsync no # 交给操作系统:最快,可能丢一大段

everysec 是官方默认,也是绝大多数场景的最优解:至多丢 1 秒数据,性能损耗很小。

AOF 重写:日志不能无限膨胀

问题:INCR counter 执行 100 万次,AOF 里就是 100 万条记录——counter 的 100 万个历史值毫无意义,恢复只需要最后一条 SET counter 1000000。

AOF 重写(BGREWRITEAOF)就是:fork 子进程,根据当前内存状态生成一份最精简的日志(等价于”用现在的数据反推最少的命令”),替换旧文件。重写期间的新写命令写入重写缓冲区,最后追加到新文件。

Redis 7.0 起 AOF 从单文件变成 multi-part AOF:基础文件(base,可能是 RDB 格式)+ 增量文件(incr)+ 一个 manifest 清单统一管理,重写不再需要”重写缓冲区追加”的老机制,实现更干净。

AOF 的优缺点

优点:丢数据少(everysec 最多丢 1 秒),日志是可读的追加命令,甚至能手动修复。

缺点:文件比 RDB 大、恢复慢(要逐条重放命令)、每秒 fsync 也有一点点性能开销。

四、混合持久化:两个都要(Redis 4.0+)

RDB 恢复快但丢得多,AOF 丢得少但恢复慢——于是 Redis 4.0 推出混合持久化,直接缝合两者优点:

1
aof-use-rdb-preamble yes   # Redis 7.x 里等价于 aof-timestamp-enabled 时代的默认行为

原理:AOF 重写时,先把当前全量数据以 RDB 格式写入新 AOF 文件的开头,之后的增量写命令再以 AOF 格式追加在后面。

恢复时:先加载 RDB 部分(快),再重放增量 AOF 命令(少)。

  • 丢数据窗口 = AOF 的 everysec(最多 1 秒)
  • 恢复速度 ≈ RDB 的载入速度 + 少量命令回放

这就是目前生产环境的默认选择。

五、生产环境怎么选?

场景 推荐方案 理由
纯缓存,丢了能回源 RDB(或干脆关持久化) 恢复快、省心
存了业务数据(计数、队列、购物车) 混合持久化 丢得少 + 恢复快
金融级、一条都不能丢 everysec + 业务层补偿(如事务消息) Redis 本质不是数据库,兜底要在业务做

一份可以直接抄的配置:

1
2
3
4
5
6
7
8
# redis.conf 持久化部分(Redis 7.x)
save 3600 1 300 100 60 10000 # RDB 自动快照
stop-writes-on-bgsave-error yes # 快照失败时拒绝写入,及时暴露问题
appendonly yes
appendfsync everysec
aof-use-rdb-preamble yes # 混合持久化
auto-aof-rewrite-percentage 100 # 比上次重写后体积翻倍才触发
auto-aof-rewrite-min-size 64mb

总结

  • RDB 是快照:fork + 写时复制,恢复快,会丢两次快照之间的数据
  • AOF 是日志:appendfsync 三档,everysec 兼顾性能与安全;重写解决膨胀
  • 混合持久化 = RDB 打底 + AOF 增量,生产首选
  • 记住那条主线:持久化的一切设计,都是”性能”与”数据安全”的权衡

下一篇讲使用 Redis 做缓存绕不开的三大经典故障:缓存穿透、缓存击穿、缓存雪崩——以及缓存和数据库的一致性怎么保。

上一页
2026-10-12 09:40:00
下一页