一、AOF 的实现方式
- 核心原理
AOF 通过将写操作命令以追加方式记录到日志文件中,重启时通过重放命令恢复数据。与 RDB 的快照机制不同,AOF 是增量记录,更适用于数据一致性要求较高的场景。 - 写入流程
- 命令执行:客户端发送写命令(如
SET key value
),Redis 先执行命令并更新内存数据。 - 缓冲区记录:将命令追加到内存中的 AOF 缓冲区(
aof_buf
),避免频繁磁盘 I/O。 - 磁盘写回:根据
appendfsync
策略(always
、everysec
、no
)决定何时将缓冲区数据同步到磁盘:- Always:每次写命令后同步,数据安全性最高但性能最低。
- Everysec:每秒同步一次,平衡性能与安全性(默认策略)。
- No:依赖操作系统控制刷盘,性能最佳但数据丢失风险最大。
- 命令执行:客户端发送写命令(如
- 数据结构绑定
在 Redis 的存储引擎(Engine
)中,每个数据库(DB
)对象会绑定writeAof
函数,确保写命令触发 AOF 日志记录。例如,执行SET
命令时,会调用db.writeAof
将命令序列化并写入缓冲区。
二、AOF 重写机制
AOF 文件会随时间增长,导致恢复速度变慢。重写通过生成最小化命令集压缩文件,其核心步骤如下:
- 触发条件
- 文件大小超过阈值(默认当前大小 ≥ 基准大小的 1.1 倍且 ≥ 64MB)。
- 手动执行
BGREWRITEAOF
命令。
- 重写过程
- Fork 子进程:主进程通过
fork
生成子进程,子进程共享内存快照(COW 机制)。 - 子进程生成新文件:子进程遍历内存数据,将键值对转换为等效的写命令(如
SET key value
),写入临时文件temp-rewriteaof-bg-pid.aof
。 - 主进程记录增量命令:重写期间,主进程将新写命令同时写入
aof_buf
和 AOF 重写缓冲区(aof_rewrite_buf
),避免数据丢失。 - 合并增量数据:子进程完成后,主进程将
aof_rewrite_buf
中的命令追加到临时文件。 - 原子替换文件:使用
rename
系统调用将临时文件替换为原 AOF 文件,完成重写。
- Fork 子进程:主进程通过
- 优化与问题
- 内存开销:
aof_rewrite_buf
与aof_buf
内容重复,可能导致内存占用翻倍。 - CPU 开销:主进程需处理
aof_rewrite_buf
写入及子进程通信,可能影响性能。 - 改进方案:Redis 7.0 引入 MP-AOF(Multi Part AOF),通过分阶段写入减少内存占用和阻塞时间。
- 内存开销:
三、AOF 与 RDB 的对比
特性 | AOF | RDB |
---|---|---|
数据恢复 | 通过重放命令,恢复时间较长。 | 二进制加载,恢复速度快。 |
文件体积 | 较大(记录所有写命令)。 | 较小(紧凑的二进制快照)。 |
数据安全性 | 支持秒级持久化(everysec )。 | 定期快照,可能丢失部分数据。 |
适用场景 | 需要强一致性的场景(如金融交易)。 | 备份、主从复制、快速恢复。 |
四、总结
AOF 通过记录写命令实现持久化,其重写机制有效解决了文件膨胀问题,但需权衡内存与 CPU 开销。在实际应用中,建议结合 RDB 使用(混合持久化模式),以兼顾性能与数据安全性。