AOF重写期间所有数据类型写入不受影响,命令同步写入aof_buf和aof_rewrite_buf_blocks两个独立缓冲区;需关注缓冲区膨胀、管道阻塞及子进程消费效率引发的OOM或延迟风险。

Redis AOF重写期间,String、Hash、List、Set、ZSet、Stream 等所有数据类型的写入行为完全不受影响——因为重写不修改任何现有数据结构,也不拦截命令执行路径。真正需要关注的,是这些写入能否被可靠捕获并最终落进新AOF文件。
重写期间新命令到底写到哪了
执行 BGREWRITEAOF 后,主进程仍照常处理所有客户端请求。每条成功执行的写命令(无论操作的是 SET 还是 XADD)会同步写入两个地方:
- 追加到内存缓冲区
aof_buf,后续按appendfsync策略刷盘(保障旧AOF不丢) - 追加到专用重写缓冲区
aof_rewrite_buf_blocks(链表结构),仅用于向子进程传递增量
这两个缓冲区完全独立:aof_buf 负责老AOF的持续更新,aof_rewrite_buf_blocks 只为子进程消费而存在。你不需要、也不能手动干预它们的写入逻辑。
为什么大key或高频Stream写入容易出问题
重写期间的稳定性瓶颈不在数据类型本身,而在缓冲区承载能力与父子进程协同效率:
-
aof_rewrite_buf_blocks是纯内存链表,无大小限制;若重写耗时长 +Stream持续XADD或大HSET批量写入,可能快速吃光可用内存(OOM) - 父进程通过匿名管道向子进程推送
aof_rewrite_buf_blocks内容;若子进程读取慢(比如磁盘IO高、CPU争抢),管道填满后write()会阻塞父进程,导致所有客户端请求延迟飙升 - 某些场景下(如
LPUSH+LTRIM频繁交替),虽命令有效,但重写子进程只基于当前内存快照生成最小命令集,不会保留中间状态——这是设计使然,不是故障
如何验证重写期间各类写入是否完整落地
不能只看 INFO persistence 里的 aof_pending_rewrite 是否为 0,要交叉验证三处:
- 检查
aof_current_size和aof_base_size:重写完成后,前者应接近后者,且aof_pending_bio_fsync应归零 - 用
redis-check-aof --fix手动校验新AOF文件语法完整性(注意:仅限停机或从节点操作) - 对比重写前后 key 数量与关键业务 key 的值(例如用
SCAN+TYPE+GET/HEXISTS/XLEN组合抽样)
特别注意:如果重写中途失败,Redis 会继续使用旧AOF恢复,但新写入已存在于 aof_buf 中并按策略落盘——所以旧AOF末尾其实已包含重写期间的部分命令,只是未被“压缩”。
生产环境必须盯住的几个硬指标
重写是否平稳,不取决于你写了什么数据类型,而取决于系统能否扛住缓冲膨胀和管道压力:
-
aof_rewrite_buffer_length(需通过调试模式或日志估算):它在源码中不直接暴露,但可通过INFO memory中mem_clients_normal异常增长间接感知 -
client-output-buffer-limit对 pub/sub 客户端的影响会被放大——因主线程一旦被管道阻塞,所有输出缓冲区都可能积压 - 子进程
fork耗时超过 1 秒?说明内存过大或 THP 开启,这会拖慢整个重写启动节奏,间接拉长风险窗口
最易被忽略的一点:auto-aof-rewrite-percentage 和 auto-aof-rewrite-min-size 触发的是「评估」,真正执行仍依赖 serverCron 周期轮询;如果你禁用了 serverCron 相关调度(如误配了 hz),重写可能迟迟不启动,导致 aof_rewrite_buf_blocks 持续累积。


















