缓解 Redis AOF 重写期间消息队列性能下降,最推荐的做法是调整自动重写触发阈值或改为业务低峰期手动触发。适用场景为写密集型业务,风险边界在于关闭自动重写可能增加 AOF 文件体积占用磁盘空间。
先说结论:通过拉长自动重写间隔或手动控制重写时间,可以避免重写操作与业务高峰重叠,从而减少延迟抖动。
- 先定位:使用 LATENCY DOCTOR 确认延迟 spike 是否与 aof_rewrite_in_progress 状态重合
- 先做:调大 auto-aof-rewrite-percentage 参数或临时关闭自动重写
- 再验证:观察业务高峰期 INFO persistence 中重写状态是否消失
命令速用版
以下命令用于临时控制 AOF 重写行为,生效立即,重启后失效:
CONFIG SET auto-aof-rewrite-percentage 0
CONFIG SET auto-aof-rewrite-min-size 0
BGREWRITEAOF
第一条和第二条用于关闭自动触发,第三条用于手动触发重写。
为什么会这样
AOF 重写本身不阻塞主线程,但 fork 子进程和最终文件切换动作会影响性能。Redis 执行 BGREWRITEAOF 时会 fork 子进程,操作系统采用 copy-on-write 机制,主进程大量写入会导致内存页复制,消耗 CPU 和内存带宽。重写完成后的原子 rename 操作会短暂阻塞主线程,导致消息队列消费延迟瞬间升高。
分步处理
第一步,检查当前持久化状态。执行 INFO persistence 命令,查看 aof_rewrite_in_progress 字段是否为 1,确认重写是否正在进行。
第二步,调整自动重写配置。在 redis.conf 中增大 auto-aof-rewrite-percentage 值,例如从 100 调整为 200,减少重写频率。生产环境建议使用 CONFIG SET 动态调整测试效果。
第三步,规划手动重写窗口。在业务低峰期执行 BGREWRITEAOF 命令,避免与消息队列写入高峰重叠。
第四步,优化操作系统内核参数。确保 vm.overcommit_memory 设置为 1,防止 fork 时因内存检查失败导致阻塞。
怎么验证是否生效
使用 LATENCY HISTORY command 查看延迟历史,确认高峰期间是否还有明显的延迟毛刺。查看 Redis 慢日志 SLOWLOG GET 10,确认是否有耗时较长的命令出现在业务高峰期。监控 INFO persistence 中的 aof_current_size 和 aof_base_size,确认文件大小增长是否符合预期。
常见坑
禁用自动重写后忘记手动维护,导致 AOF 文件无限增长占满磁盘。fork 子进程时如果内存占用过高,可能触发操作系统 OOM Killer 杀死 Redis 进程。使用透明大页 Transparent Hugepage 可能导致 fork 性能严重下降,建议在操作系统层面关闭。
常见问题
AOF 重写会阻塞 Redis 主线程吗?
重写过程不阻塞,但 fork 瞬间和最终文件切换会短暂阻塞主线程。
如何查看 AOF 重写进度?
执行 INFO persistence 命令,查看 aof_rewrite_percent 字段获取百分比进度。
消息队列场景建议用 AOF 还是 RDB?
对数据完整性要求高选 AOF,对性能敏感且允许少量丢失选 RDB 或混合持久化。
参考来源
- Redis Documentation - Persistence: https://redis.io/docs/latest/operate/oss-and-stack/management/persistence/
- Redis Documentation - Latency Monitoring: https://redis.io/docs/latest/operate/oss-and-stack/management/optimization/latency/