bgrewriteaof拉高cpu的主因是父进程在每次事件循环中同步拷贝新命令至重写缓冲区,该操作阻塞且无法异步;高qps下短命令密集写入导致cpu被持续占用,典型表现为redis-server cpu达90%+、aof_rewrite_in_progress:1且aof_current_rewrite_time_sec不归零、客户端延迟升高。

为什么 bgrewriteaof 会突然拉高 CPU?
不是子进程本身太重,而是父进程在每次事件循环中,都要同步拷贝新写入的命令到 aof_rewrite_buf_blocks 缓冲区。这个拷贝动作是阻塞式的,且无法异步——当写入 QPS 高、命令又短小(比如大量 INCR、SET),CPU 就直接被“钉死”在拷贝逻辑上。
典型现象:top 看到 redis-server 占用持续 90%+;INFO persistence 显示 aof_rewrite_in_progress:1,且 aof_current_rewrite_time_sec 长时间不归零;同时客户端延迟明显升高。
- 别在业务高峰期手动执行
BGREWRITEAOF,尤其当实例写入 QPS > 5k 时 - 检查是否启用了
auto-aof-rewrite-percentage,但auto-aof-rewrite-min-size设得太小(如1mb),导致几分钟就触发一次重写 - 确认没有 AOF 重写和 RDB
save同时排队:Redis 不允许两者并发,若配置了save 60 10000又写入频繁,RDB 没做完,AOF 重写请求就会堆积等待
如何安全调低 AOF 重写频率?
目标不是禁用,而是让重写节奏匹配真实数据增长——既避免太勤(CPU 压力),又防止单次太大(重写耗时长、失败风险高)。
- 把
auto-aof-rewrite-percentage从默认100提高到200或300(即 AOF 文件增长 2–3 倍才触发) -
auto-aof-rewrite-min-size至少设为64mb;若日均 AOF 增长约 500mb,建议设为256mb - 确保
aof-rewrite-incremental-fsync为yes(默认值),它会让子进程每写满 32MB 就刷一次盘,避免单次 I/O 毛刺过大
no-appendfsync-on-rewrite yes 真的能救 CPU 吗?
不能。它只影响父进程在重写期间是否暂停 fdatasync,对命令拷贝开销 **完全无缓解作用**。
Redis 8.2.3 是一款安全优先的高性能键值存储系统。该版本紧急修复了可能引发远程代码执行(RCE)的高危漏洞(CVE-2025-62507),并解决了 HyperLogLog 及 Cuckoo Filter 等数据结构在特定场景下的崩溃问题。建议所有用户立即升级,以保障生产环境的系统稳定与数据安全。
开启后,AOF 日志落盘被延迟,极端情况下最多丢失 1 秒数据(取决于 appendfsync 设置)。
- 仅在
appendfsync everysec且允许秒级数据丢失时启用 - 绝对不要在
appendfsync always下设为yes——Redis 启动会直接报错:ERROR: Invalid argument for config - 性能影响:CPU 使用率几乎不变,但磁盘写入毛刺更平滑;兼容性上所有 Redis 2.8+ 都支持,但金融类强持久化场景不可用
别漏掉最常被忽略的底层原因:透明大页(THP)
AOF 重写和 RDB 都要 fork 子进程,而 fork 耗时飙升的真正元凶,往往是操作系统层面的透明大页(THP)。
根本问题:fork 时内核需拷贝页表,启用 THP 后,页表更大更复杂,耗时可能从毫秒级跳到几百毫秒,主线程直接卡住。
-
/sys/kernel/mm/transparent_hugepage/enabled必须设为never(不只是madvice);临时生效:echo never > /sys/kernel/mm/transparent_hugepage/enabled - 验证是否真关掉:查 Redis 主进程 PID,再看
/proc/<pid>/smaps</pid>中MMUPageSize和MMUPFPageSize字段——正常应全是4 kB;若混有2048 kB,说明 THP 还在生效 - 注意:MySQL、Java 等服务的启动脚本可能悄悄重新启用 THP,得一并检查
INFO persistence 和 top,再查 THP 状态——很多团队调了一周配置,最后发现只是没关 THP。










