bigywater.tech
Redis · 59

AOF Rewrite 过程

AOF 只追加、从不修改,文件会越长越大。AOF Rewrite 就是把「重放后得到当前数据集所需的最少命令」重新写一遍,替换掉旧的。Redis 7 之后 AOF 的文件结构也变了(不再是单个 appendonly.aof)。这篇直接看 appendonlydir 里的文件、manifest 的变化和日志,把一次重写从头到尾走一遍。

10.7 → 1.44 MB
30 万次 INCR + 5 万个 SET 的 incr 文件,重写后变成的 base
3 种文件
appendonlydir:base(RDB 格式)、incr(命令)、manifest(清单)
192%
自动触发重写时,AOF 相对 base 的增长(配置 percentage = 100)

AOF 现在长什么样

实测 · 本机执行输出
        89  appendonly.aof.1.base.rdb
         0  appendonly.aof.1.incr.aof
       102  appendonly.aof.manifest
manifest:
file appendonly.aof.1.base.rdb seq 1 type b
file appendonly.aof.1.incr.aof seq 1 type i startoffset 0

启动一个新的 appendonly 实例:appendonlydir 里有 base(appendonly.aof.1.base.rdb)、incr(appendonly.aof.1.incr.aof)和 appendonly.aof.manifest。manifest 列出当前有效的文件、序号和类型(b = base,i = incr)。

一次重写前后

为了看清过程,先把自动重写关掉(auto-aof-rewrite-percentage 0)
实测 · 本机执行输出
重写前:
        89  appendonly.aof.1.base.rdb
  10688913  appendonly.aof.1.incr.aof
       102  appendonly.aof.manifest
manifest:
file appendonly.aof.1.base.rdb seq 1 type b
file appendonly.aof.1.incr.aof seq 1 type i startoffset 0
> BGREWRITEAOF
"Background append only file rewriting started"
重写耗时(INFO aof_rewrite_in_progress 从 1 变 0):约 0.15 s;aof_last_rewrite_time_sec = 0;aof_last_bgrewrite_status = ok
重写后:
   1439002  appendonly.aof.2.base.rdb
         0  appendonly.aof.2.incr.aof
       107  appendonly.aof.manifest
manifest:
file appendonly.aof.2.base.rdb seq 2 type b
file appendonly.aof.2.incr.aof seq 2 type i startoffset 350000

写入 30 万次 INCR counter 和 5 万个 SET 之后,incr 文件有 10.7 MB。BGREWRITEAOF 完成(约 0.15 s)后,文件变成 appendonly.aof.2.base.rdb(1.44 MB)加一个空的新 incr;manifest 指向新的一对,旧文件被删除。30 万次 INCR 折叠成一条 counter = 300000。manifest 里的 startoffset 350000 我没有追究它的精确定义(与写入的命令数 350000 相同)。

base 是 RDB 格式

实测 · 本机执行输出
appendonly.aof.2.base.rdb: 前 9 字节 = b'REDIS0015'
是 RDB 格式(aof-use-rdb-preamble 默认 yes)。DBSIZE = 50001  counter = 300000

新 base 的文件头是 REDIS0015——RDB。默认 aof-use-rdb-preamble yes,重写产出的 base 是 RDB 快照,之后的增量才是命令文本。混合持久化的详细对比见第 61 篇。

日志里的时间线

实测 · 本机执行输出
  Creating AOF base file appendonly.aof.1.base.rdb on server start
  Creating AOF incr file appendonly.aof.1.incr.aof on server start
  Creating AOF incr file appendonly.aof.2.incr.aof on background rewrite
  Background append only file rewriting started by pid 33732
  Successfully created the temporary AOF base file temp-rewriteaof-bg-33732.aof
  Fork CoW for AOF rewrite: current 0 MB, peak 0 MB, average 0 MB
  Background AOF rewrite terminated with success
  Successfully renamed the temporary AOF base file temp-rewriteaof-bg-33732.aof into appendonly.aof.2.base.rdb
  Background AOF rewrite finished successfully

关键顺序:先 Creating AOF incr file … on background rewrite(新写入从这一刻起进新 incr),再 Background append only file rewriting started by pid …(fork),子进程写 temp-rewriteaof-bg-….aof,成功后 rename 为新的 base,最后 Background AOF rewrite finished successfully。重写期间的写入不需要在内存里缓冲、再补写——它们直接进新的 incr 文件(见第 60 篇)。

自动触发

实测 · 本机执行输出
> CONFIG SET auto-aof-rewrite-percentage 100
"OK"
日志: Starting automatic rewriting of AOF on 192% growth
触发时写入了 36000 个 key;aof_base_size = 1439002,aof_current_size = 4379938(触发条件:current ≥ base×2 且 ≥ 1 MB)

自动重写关掉之后,把 auto-aof-rewrite-percentage 设回 100(auto-aof-rewrite-min-size 设 1 MB)并继续写入,日志出现 Starting automatic rewriting of AOF on 192% growth:当时 aof_base_size = 1439002、aof_current_size = 4379938。触发点是 AOF 相对 base 的增长(百分比)超过阈值且大小超过 min-size;实际触发时的 192% 大于 100%,因为我的写入是每批 2000 个 key,检查有间隔,没有精确停在 100%。

分步演示:一次 AOF 重写

AOF Rewrite
本步涉及的文件

    本文用到的工具与边界

    • 本机 macOS 27 / Redis 8.10.2 独立实例(本机回环端口,save 关闭),redis-cli 风格输出由自写的 RESP 客户端打印;计时用 time.perf_counter,数字每次运行会有小幅抖动。appendonly yes、appendfsync everysec;重写演示时自动重写被关闭
    • 没有验证:数据集很大时重写对主进程的影响(见第 66 篇)、重写失败与重试、aof-use-rdb-preamble no 时的 base 格式(第 61 篇)、manifest 各字段的完整含义
    京ICP备2026067502号-1京公网安备11010502063487号