如果说 RDB 快照是 Redis 持久化的"快照相机",那么 AOF(Append-Only File)就是它的"操作录像机"。
AOF 通过记录每个写命令,提供了近乎实时的数据持久化能力。然而,随着写入量增长,AOF 文件会不断膨胀,带来磁盘压力与恢复效率下降的问题。
为此,Redis 引入了 AOF 重写(AOF Rewrite) 机制,并在 4.0 版本后进一步推出 混合持久化(Hybrid Persistence),将 RDB 的紧凑性与 AOF 的安全性完美融合。
一、AOF 基础机制回顾
AOF 默认关闭,启用后(appendonly yes),Redis 会将每个写命令以协议格式追加到 appendfilename 指定的文件末尾。
1. 同步策略(appendfsync)
| 策略 | 数据安全性 | 性能影响 | 说明 |
|---|---|---|---|
always |
最高(每次写都 fsync) | 极高 I/O 延迟 | 每秒仅支持几百次写入 |
everysec |
高(最多丢失 1 秒数据) | 可接受 | 推荐生产使用 |
no |
依赖 OS flush | 最低 | 不可控,不建议 |
二、AOF 重写(AOF Rewrite)机制详解
1. 为何需要重写?
原始 AOF 文件存在大量冗余。例如:
text
INCR counter → counter = 1
INCR counter → counter = 2
INCR counter → counter = 3
其实等价于一条命令:SET counter 3。重写的目的就是用最少的命令重建当前数据集,大幅压缩文件体积。
2. 重写流程(非阻塞设计)
Redis 通过 BGREWRITEAOF 触发后台重写,全程不阻塞主进程:
关键点:重写期间的新写入不会丢失 ,因为主进程会将它们暂存到 aof_rewrite_buf_blocks,并在子进程完成后追加到新 AOF 文件末尾。
3. 自动重写触发条件
由以下两个配置共同控制:
conf
auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb
- 当前 AOF 文件大小 >
min-size且 - 当前大小 > 上次重写后大小 × (1 +
percentage/100)
示例:上次重写后 AOF 为 100MB,当前达 201MB(>100×2),则触发自动重写。
三、混合持久化(RDB + AOF Preamble)
1. 设计动机
纯 AOF 恢复慢(需重放数百万条命令),纯 RDB 可能丢数据。混合模式取两者之长:
- 文件前半部分:RDB 格式的全量快照(加载极快)
- 文件后半部分:AOF 格式的增量命令(保证数据不丢)
2. 启用方式
conf
appendonly yes
aof-use-rdb-preamble yes # Redis 4.0+ 默认开启
查看 AOF 文件开头:若包含
REDIS魔数,则为混合格式。
什么是"魔数(Magic Number)"?
在 Redis 中,RDB 文件的前 5 个字节固定为 REDIS (ASCII 编码),这是 RDB 格式的标识。当启用 混合持久化 (aof-use-rdb-preamble yes)后,AOF 文件的开头也会写入这 5 字节的 RDB 魔数,后面再追加 AOF 命令。
因此:
- 纯 AOF 文件:开头是明文 Redis 协议命令 (如
2\r\n$6\r\nSELECT...) - 混合 AOF 文件:开头是二进制
REDIS字符串
验证魔数
使用 od(几乎在所有 Linux 容器中都存在)
bash
head -c5 appendonly.aof| od -t c
如何判断结果?
-
如果输出包含:文本
R E D I S→ 是混合持久化
示例
bash
root@810a7de89bde:~# head -c5 /data/appendonly.aof| od -t c
0000000 R E D I S
0000005
-
如果输出类似:文本
* 2 \r \n $→ 是纯 AOF
3. 恢复流程
- Redis 检测到 AOF 文件含 RDB preamble;
- 先加载 RDB 部分(毫秒级);
- 再重放后续 AOF 命令(仅需处理少量增量)。
四、常用 AOF 相关命令与配置
| 命令 / 配置 | 作用 | 注意事项 |
|---|---|---|
BGREWRITEAOF |
手动触发 AOF 重写 | 非阻塞,生产可用 |
CONFIG SET appendonly yes |
动态开启 AOF | 开启后会立即触发一次 BGREWRITEAOF |
INFO PERSISTENCE |
查看 aof_enabled, aof_current_size, aof_rewrite_in_progress 等指标 |
运维监控必备 |
appendfilename |
AOF 文件名(默认 appendonly.aof) |
可配合 dir 指定路径 |
aof-load-truncated |
是否加载被截断的 AOF 文件 | 默认 yes,避免启动失败 |
五、持久化方案对比:RDB vs AOF vs 混合
| 维度 | RDB | AOF | 混合持久化 |
|---|---|---|---|
| 数据安全性 | 可能丢失最后一次快照后数据 | 最多丢失 1 秒(everysec) |
同 AOF |
| 恢复速度 | ⚡ 极快(直接加载二进制) | 慢(重放命令) | ⚡ 快(先加载 RDB) |
| 文件大小 | 小 | 大(尤其高频写) | 中等(RDB 紧凑 + 少量 AOF) |
| 运行时开销 | 仅 fork 时瞬时高 | 持续 I/O(尤其 always) |
同 AOF |
| 适用场景 | 备份、快速重启 | 高可靠性、审计 | 推荐生产默认方案 |
最佳实践 :启用混合持久化 +
appendfsync everysec,平衡安全、性能与恢复效率。
常用恢复与诊断命令清单
| 命令 | 用途 | 示例 |
|---|---|---|
redis-check-rdb <file> |
验证 RDB 文件完整性 | redis-check-rdb ./dump.rdb |
redis-check-aof --fix <file> |
修复并截断损坏的 AOF | redis-check-aof --fix ./appendonly.aof |
INFO PERSISTENCE |
查看持久化状态 | bgsave_in_progress, aof_enabled, latest_fork_usec |
CONFIG GET dir / dbfilename / appendfilename |
确认文件路径 | --- |
DEBUG LOADAOF |
(开发用)强制重新加载 AOF | 仅限测试环境 |
CONFIG REWRITE |
重写 redis.conf(保留运行时配置) | 用于固化持久化设置 |
六、典型应用场景
-
金融交易系统
要求"不能丢账",混合持久化确保崩溃后数据完整,且恢复时间满足 SLA。
-
用户会话存储
虽可容忍少量丢失,但需快速恢复服务------混合模式比纯 AOF 快 5--10 倍。
-
审计与合规
AOF 文件可作为操作日志溯源(需配合
aof-rewrite-incremental-fsync避免大文件写入卡顿)。 -
云托管 Redis 服务
云厂商(如 AWS ElastiCache、阿里云 Redis)默认启用混合持久化,兼顾成本与可靠性。
七、高频面试题
Q1:AOF 重写期间,新的写命令如何保证不丢失?
答 :主进程在重写期间会将新命令同时写入原 AOF 文件 和 内存中的
aof_rewrite_buf_blocks缓冲区。子进程完成后,主进程将缓冲区内容追加到新 AOF 文件末尾,确保零丢失。
Q2:混合持久化文件的结构是怎样的?
答 :文件开头是标准 RDB 格式(以
REDIS魔数起始),后面紧跟 AOF 格式的增量命令。Redis 启动时能自动识别并分阶段加载。
Q3:为什么 BGREWRITEAOF 不会阻塞 Redis?
答 :它通过
fork()创建子进程执行重写,主进程继续服务。写时复制(COW)保证子进程看到一致内存视图,而增量命令由主进程缓冲。
Q4:AOF 重写会导致磁盘写满吗?如何预防?
答:可能。重写需额外磁盘空间(≈当前内存大小)。建议:
- 监控磁盘使用率;
- 设置
auto-aof-rewrite-min-size避免小文件频繁重写;- 使用
aof-rewrite-incremental-fsync yes分批刷盘。
Q5:能否在运行时从 RDB 切换到 AOF?
答 :可以。执行
CONFIG SET appendonly yes,Redis 会自动触发一次BGREWRITEAOF生成初始 AOF 文件,无需重启。