redis aof重写期间访问变慢的直接原因是fork后父进程写入触发大量写时复制页表拷贝,导致系统调用延迟升高;no-appendfsync-on-rewrite仅跳过fsync以缓解i/o争抢,并非解决内存拷贝问题。

Redis AOF重写期间访问变慢的直接原因
根本不是重写本身太耗 CPU,而是 fork() 后子进程做 AOF 重写时,父进程持续写入,触发大量「写时复制(Copy-on-Write)」页表拷贝。尤其当内存中存在大量被修改的键值对时,Linux 内核需为每个被改写的内存页创建副本,导致父进程系统调用延迟升高、响应变卡。
典型现象包括:INFO commandstats 中 cmdstat_set 等命令的 usec_per_call 显著上升;redis-cli --latency 测出毛刺明显;监控看到 used_memory_rss 在重写开始后快速膨胀。
no-appendfsync-on-rewrite 真实作用与启用条件
这个配置不阻止 AOF 写入,只让父进程在重写进行中**跳过 fsync() 调用**,把 AOF 缓冲区暂存到内核 page cache,等重写结束再批量刷盘。它解决的是父子进程争抢磁盘 I/O 和 fsync() 阻塞问题,而非内存拷贝开销。
Redis 缓存和数据结构管理技能。通过自然语言操作 Redis,支持 String、Hash、List、Set、ZSet、Stream 等数据结构操作。当用户提到 Redis、缓存、消息队列、会话存储时使用此技能。
- 仅在
appendfsync设置为everysec时生效(always下强制同步,no下本就不 fsync) - 启用后,极端情况下可能丢失最多 2 秒数据(重写期间 + 上一个 everysec 周期)
- 必须配合
auto-aof-rewrite-percentage和auto-aof-rewrite-min-size合理设置,避免重写过于频繁
比 no-appendfsync-on-rewrite 更关键的优化点
很多人开了这个参数就以为万事大吉,其实真正影响服务稳定性的常是其他配置或使用方式:
-
vm.overcommit_memory必须设为1,否则fork()可能因内存检查失败而阻塞甚至失败 - AOF 重写期间若父进程同时执行
BGREWRITEAOF或BGSAVE,会叠加 fork 压力,应禁止并发执行 - 使用
appendfilename指向 SSD 分区,避免和主实例日志混在一块机械盘上 - 如果业务允许,考虑关闭 AOF、纯用 RDB + 从库备份,彻底规避重写问题
验证是否真的缓解了延迟毛刺
不能只看配置开了没,得观测真实指标:
- 用
redis-cli INFO persistence查aof_rewrite_in_progress和aof_last_rewrite_time_sec,确认重写确实发生且耗时不异常 - 对比开启前后
cat /proc/$(pidof redis-server)/status | grep -i vmsize,观察 RSS 增速是否平缓 - 用
strace -p $(pidof redis-server) -e trace=fsync,write -T 2>&1 | grep fsync确认重写期间fsync()调用是否暂停(注意:仅用于调试,勿长期运行)
重写慢的本质是内存+I/O+内核行为的耦合,单独调一个参数很难根治,得从 fork 效率、写负载节奏、落盘路径三处一起看。










