AOF rewrite 卡住磁盘 I/O 的主因是子进程顺序写入大量数据超出磁盘写吞吐能力,导致 %util 接近 100%、w_await 升高、wkB/s 远低于理论值;同时主进程的读盘操作(如 RDB 生成、旧 AOF 刷盘)会加剧读写干扰。

为什么 AOF rewrite 会卡住磁盘 I/O?
AOF rewrite 本质是 Redis 主进程 fork 出子进程,由子进程把当前数据库状态全量写成新 AOF 文件。这个过程不涉及网络或 CPU 密集计算,但会持续顺序写入大量数据(可能几百 MB 到数 GB),对磁盘写吞吐能力极其敏感。一旦磁盘写入速度跟不上 rewrite 速率,就会出现 bgrewriteaof 长时间阻塞、AOF 文件增长异常、甚至触发 redis-server 被系统 OOM killer 杀掉。
用 iostat 快速定位磁盘写瓶颈
别猜,直接看实时 I/O 行为。在 rewrite 过程中执行:
iostat -x 1
重点关注这几列:
-
%util:接近 100% 表示磁盘忙饱和,是首要怀疑对象 -
w_await:写请求平均等待毫秒数,持续 >10ms 就算偏高,>50ms 基本确认是磁盘响应慢 -
wkB/s:实际写入带宽,对比磁盘标称顺序写性能(如 SATA SSD 通常 400–500 MB/s,NVMe 可达 2–3 GB/s) -
avgqu-sz:写队列平均长度,>1 说明请求已在排队
如果 wkB/s 远低于磁盘理论值,且 %util 拉满,基本可断定是磁盘硬件或驱动层限制,不是 Redis 配置问题。
rewrite 期间磁盘读也在拖后腿?
很多人忽略一点:AOF rewrite 子进程本身不读盘,但主进程仍要响应客户端、持久化 RDB(如果开启)、刷写旧 AOF 缓冲区——这些操作都会争抢磁盘读带宽。尤其当旧 AOF 文件很大、且启用了 appendfsync everysec 时,内核后台线程会频繁将 page cache 中的 AOF 数据刷到磁盘,造成读写混杂干扰。
验证方法:
- 用
iostat -x 1同时观察rKB/s和wKB/s,若 rewrite 期间读流量也明显上升,说明有其他读盘任务在并行发生 - 检查是否同时运行了
save或bgsave,RDB 生成也会读取整个内存快照 - 确认
no-appendfsync-on-rewrite yes已启用——它能禁止 rewrite 期间触发fsync,减少写抖动
SSD 老化或文件系统配置不当的真实影响
即使用的是 NVMe,也可能因底层问题掉速。常见被忽视的点:
- SSD 剩余空间 w_await 突然飙升
- 文件系统挂载参数没开
noatime或barrier=0(后者需确认数据安全性可接受),每次写都多一次元数据更新 - AOF 文件放在 LVM 或 overlayfs(如 Docker 默认存储驱动)上,额外引入一层 I/O 转发开销
- ext4 默认启用
journal=ordered,rewrite 大量写入时 journal 会成为瓶颈;生产环境建议改用journal=writeback或直接换 xfs
临时验证磁盘裸写能力,可用:
dd if=/dev/zero of=/path/to/testfile bs=4M count=1024 oflag=direct
,对比结果与 iostat 中 rewrite 时的 wkB/s 是否接近。
rewrite 不是调参能硬扛出来的,磁盘吞吐见顶就是见顶。宁可关掉 AOF 改用 RDB + 从库备份,也别让 rewrite 在慢盘上反复失败重试——那只会把磁盘队列越积越长,连带主进程延迟一起恶化。











