redis 7.0 废弃旧版aof重写机制,因其依赖fork+全量dump易引发oom、主线程阻塞及淘汰压力放大;改用multi-part aof后,新增命令异步追加至.incr.aof,base文件仅存快照,合并由后台线程完成,内存稳定在几十mb。

Redis 7.0 废弃旧版单个 AOF 重写机制,不是为了“换概念”,而是因为 fork + 全量内存 dump 的模式在现代高写入、大内存场景下已不可控——它会真实触发 OOM、阻塞主线程、放大淘汰压力,且无法水平收敛内存开销。
旧版 bgrewriteaof 为什么必须 fork 子进程
Redis 6.x 及之前版本的 bgrewriteaof 本质是:子进程遍历整个内存数据集,逐键生成最小化命令序列。这要求子进程看到“某一时刻”的完整快照,而 Linux fork 是唯一能低成本获得该视图的方式(靠 COW)。但代价明确:
- 主进程内存越大,
fork耗时越长,实测 20GB 内存常卡住 300ms+,期间所有请求延迟毛刺 - COW 页复制导致
used_memory_rss瞬间翻倍,mem_fragmentation_ratio轻易突破 2.0 - 子进程看不见 fork 后的新写入,所以必须依赖
aof_rewrite_buf缓冲区暂存增量——这块内存无上限,写压一大就涨到 GB 级
aof_rewrite_buf 消失后,增量命令去哪了
Redis 7.0 不再需要这个缓冲区,因为它根本不再做“重建历史”式的重写。取而代之的是 Multi-part AOF 的滚动合并逻辑:
Redis 缓存和数据结构管理技能。通过自然语言操作 Redis,支持 String、Hash、List、Set、ZSet、Stream 等数据结构操作。当用户提到 Redis、缓存、消息队列、会话存储时使用此技能。
- 新写入直接追加到最新
incr_*.aof文件,由aof-write-thread异步刷盘,缓冲区仅存几 KB~MB 待写文本 -
base.aof(或*.base.rdb)只存静态快照,由轻量级子进程生成,生命周期极短,不读增量 - 后台线程执行
aof-rewrite-diff,只读取少量incr_*.aof内容做合并,内存占用稳定在几十 MB
为什么不能保留单文件 + 改进重写逻辑
单文件结构和“增量重写”在设计上互斥:
- 单个
appendonly.aof必须保证命令流绝对连续、可顺序重放;一旦拆成 base + incr,就必须有manifest.aof管理加载顺序和有效性 - 若强行在单文件里做“分段写入”,崩溃恢复时无法判断哪些命令已落盘、哪些被截断,
redis-check-aof --fix将失效 - 主从复制依赖全局偏移量(
REPLCONF ACK),多文件结构通过 manifest 维护逻辑连续性,单文件无法承载该元数据
升级后你真正要检查的三件事
别只看版本号。Redis 7.0 默认启用 Multi-part,但配置错误会让它退化回旧模式:
- 运行
CONFIG GET aof-use-rdb-preamble,返回必须是no(yes表示走混合 RDB+AOF 单文件,不是 Multi-part) - 检查数据目录:必须存在
base.aof(或*.base.rdb)、至少一个incr_*.aof、以及manifest.aof - 日志中应出现
Creating new incr AOF file或Starting automatic rewriting of AOF on base.aof size,而非Background append only file rewriting started
最容易被忽略的是:aof-use-rdb-preamble no 这个配置项一旦设错,Multi-part 的所有优势——无大块缓冲、不 fork 全量、后台平滑合并——全部失效。它不是“锦上添花”,而是整个新机制的开关。










