Redis 是一个内存数据库,数据主要存储在内存中,因此一旦进程退出或服务器宕机,数据就会丢失。为了解决这个问题,Redis 提供了两种持久化方式:RDB(Redis Database) 和 AOF(Append Only File) ,以及从 4.0 版本开始引入的混合持久化。
一、RDB 持久化
RDB 是一种快照(snapshot) 持久化方式:在指定时间间隔内,将内存中的数据集以二进制形式写入磁盘,生成一个 dump.rdb 文件。
1.1 触发机制
-
手动触发
SAVE:阻塞 Redis 主进程,直到 RDB 文件创建完成。生产环境不建议使用。BGSAVE:fork 一个子进程负责创建 RDB 文件,主进程继续处理客户端请求(仅 fork 期间短暂阻塞)。
-
自动触发
通过
redis.conf配置save指令,例如:bashsave 900 1 # 900 秒内至少有 1 次修改 save 300 10 # 300 秒内至少有 10 次修改 save 60 10000 # 60 秒内至少有 10000 次修改满足任一条件,Redis 就会自动执行
BGSAVE。 -
其他自动触发场景
- 主从复制全量同步时,主节点会执行
BGSAVE生成 RDB 并发送给从节点。 shutdown命令且未开启 AOF 时,会执行一次SAVE。debug reload命令也会触发 RDB 保存。
- 主从复制全量同步时,主节点会执行
1.2 文件格式
RDB 文件是一个经过压缩的二进制文件,结构大致如下:
lua
+----------+---------+-----------+-----------+ ... +--------+----------+
| "REDIS" | RDB_VER | AUX 段 | 数据库段 | ... | EOF | CHECKSUM |
+----------+---------+-----------+-----------+ ... +--------+----------+
- 魔数(Magic Number) :5 字节
"REDIS",用于快速识别 RDB 文件。 - 版本号(RDB Version) :4 字节 ASCII 数字,例如
"0009"(v9),表示 RDB 格式版本。当前最新版本为 10(Redis 7.0+ 使用 v10)。 - AUX 字段(可选) :存储键值对形式的元信息,例如
redis-ver、redis-bits、ctime、used-mem等。 - 数据库段:依次存储每个非空数据库的数据,每个数据库包含若干键值对。
- EOF 标记 :固定值
0xFF1 字节,表示数据部分结束。 - 校验和(Checksum) :8 字节无符号整数,CRC64 校验和,用于验证文件完整性(Redis 5.0+ 强制启用)。
1.3 优缺点
| 优点 | 缺点 |
|---|---|
| 文件紧凑:二进制文件体积小,适合备份和灾难恢复。 | 可能丢失数据:若在两次快照之间发生宕机,最后一次快照后的所有修改都会丢失。 |
| 恢复速度快:直接加载 RDB 到内存,比 AOF 的日志重放快得多。 | fork 开销:当数据集较大时,fork 子进程可能耗时,导致主进程短暂阻塞(尤其是大内存服务器)。 |
| 对性能影响相对小:子进程执行 I/O,主进程仅 fork 时阻塞。 | 不实时:无法做到秒级持久化。 |
二、AOF 持久化
AOF 以追加写日志的方式记录每个写操作(以 Redis 协议格式),服务器启动时通过重放日志来重建数据。
2.1 工作流程
- 命令追加 :所有写命令以文本协议格式追加到
aof_buf缓冲区。 - 文件同步:根据配置的策略,将缓冲区内容同步到磁盘的 AOF 文件。
- 文件重写 :AOF 文件过大时,后台重写(
BGREWRITEAOF)生成一个最小命令集的新 AOF 文件,覆盖旧文件。 - 重启加载:服务器启动时优先加载 AOF 文件(如果同时开启 RDB 和 AOF,则 AOF 优先)来恢复数据。
2.2 同步策略(appendfsync)
| 配置值 | 行为 | 性能 | 安全性 |
|---|---|---|---|
always |
每次写命令都调用 fsync 同步到磁盘 |
最慢 | 最多丢失一个命令(已写入但未 fsync 的数据可能丢失,但 always 下每个命令后都 fsync,几乎不丢失) |
everysec |
每秒执行一次 fsync,可能将多个命令合并在一次同步中 |
折中 | 最多丢失最近一秒的数据(默认推荐) |
no |
由操作系统决定何时刷盘(通常 30 秒左右) | 最快 | 可能丢失大量数据 |
2.3 AOF 重写机制
随着写操作增多,AOF 文件会越来越大。重写的作用是:
- 去除冗余命令(如多次
INCR合并为一条SET)。 - 删除已超时或已被删除的 key 相关命令。
- 生成一个最小且完整的数据集命令集合。
重写过程:
- 主进程 fork 一个子进程。
- 子进程根据当前内存数据生成新的 AOF 文件(先写到临时文件)。
- 主进程在此期间继续处理请求,并将新写入命令同时记录到旧的 AOF 缓冲区 和重写缓冲区。
- 子进程完成后,主进程将重写缓冲区中的增量命令追加到新 AOF 文件末尾。
- 用新 AOF 文件原子替换旧文件。
触发重写的条件(redis.conf):
arduino
auto-aof-rewrite-percentage 100 # 文件大小比上次重写后增长 100%
auto-aof-rewrite-min-size 64mb # 最小体积达到 64MB 才触发
2.4 优缺点
| 优点 | 缺点 |
|---|---|
数据安全性高 :everysec 下最多丢 1 秒数据,always 下几乎不丢数据。 |
文件体积大:AOF 是文本格式,且记录所有写操作,通常比 RDB 大。 |
可读性强 :AOF 文件是纯文本,即使误操作(如 FLUSHALL)也可以手动编辑文件删除最后一两条命令后恢复。 |
恢复速度慢:重启时需要逐条执行命令,比加载 RDB 慢很多。 |
| 自动重写:可以控制文件大小,避免无限增长。 | 对性能有一定影响 :尤其是 always 策略,磁盘 I/O 开销大。 |
三、RDB vs AOF 对比总结
| 对比项 | RDB | AOF |
|---|---|---|
| 原理 | 定期内存快照 | 记录所有写命令日志 |
| 数据完整性 | 可能丢失最后一次快照后的数据 | everysec 丢 1 秒,always 几乎不丢 |
| 文件大小 | 较小(二进制压缩) | 较大(文本,但重写后可缩小) |
| 恢复速度 | 快(直接加载数据) | 慢(重放命令) |
| 对性能影响 | fork 子进程时短暂阻塞,I/O 压力小 | 写入和 fsync 增加磁盘 I/O |
| 适用场景 | 对数据丢失不敏感、追求快速重启和备份 | 对数据安全要求高,如金融、交易系统 |
| 可读性 | 不可读 | 可读,便于分析或紧急修复 |
四、混合持久化(Redis 4.0+)
为了结合 RDB 和 AOF 的优点,Redis 4.0 引入了混合持久化。当 AOF 重写时,不再生成纯文本命令,而是先生成当前内存数据的 RDB 快照(二进制格式),再追加重写期间的增量命令(以 AOF 格式)。最终生成的 AOF 文件结构为:
css
[RDB 数据] [AOF 增量命令]
- 优点:重启恢复时,先快速加载 RDB 部分,再执行少量 AOF 命令,既快又完整。
- 开启方式 :
aof-use-rdb-preamble yes(Redis 5.0+ 默认开启)。 - 兼容性:旧版本 Redis 无法识别这种混合格式,但会忽略 RDB 部分直接读取 AOF 命令(可能导致数据丢失),因此升级后不建议降级。
五、如何选择与最佳实践
-
仅用作缓存,允许大量数据丢失
→ 可以不开启持久化,或只开 RDB(如每 15 分钟一次)。
-
既要性能,又不想丢失太多数据
→ 推荐 RDB + AOF(
appendfsync everysec)同时开启。恢复时 AOF 优先。→ 从 Redis 4.0 起开启混合持久化。
-
数据安全性极高(如金融交易)
→ 开启 AOF
always,但性能会明显下降。可考虑使用 SSD 并优化fsync策略。 -
大数据集恢复速度要求高
→ 优先使用 RDB 或混合持久化。
-
主从复制环境
- 主节点可不开持久化,但从节点必须开启持久化(否则主节点重启后从节点会清空数据)。
- 主节点关闭持久化可提高性能,但需确保从节点有完整数据备份。
-
定期备份
- RDB 文件非常适合异地备份(每天 cp 或 scp 到其他机器)。
- 如果只用 AOF,也建议定期
BGREWRITEAOF减少文件大小。
六、常见问题与故障处理
- RDB 文件损坏 :
redis-check-rdb工具可以检查并尝试修复。 - AOF 文件损坏 :
redis-check-aof --fix可截断损坏部分。 - fork 子进程失败 :检查系统内存是否不足(overcommit_memory 设置),或使用
vm.overcommit_memory=1。 - AOF 文件过大导致重启缓慢 :开启自动重写,或手动执行
BGREWRITEAOF。 - 突然断电后 AOF 不完整 :Redis 启动时会自动截断到最后一个完整命令,也可用
redis-check-aof修复。
总结
- RDB 适合备份、快速恢复、对数据丢失容忍度较高的场景。
- AOF 适合高数据安全性、可接受恢复时间稍长的场景。
- 混合持久化 结合两者优点,是生产环境的推荐配置。
没有完美的持久化方案,需要根据业务对数据一致性、性能、恢复速度的权衡来选择合适的策略。通常建议同时开启 RDB 和 AOF(everysec) ,并开启混合持久化,同时配合定期备份和监控。