登录
推荐 文章 Go 技术 课程 下载 专题 AI
首页 >  数据库 >  Redis

Redis AOF rewrite 期间如何判断磁盘与内存压力

来源:17golang原创

时间:2026-09-12 19:37:31 501浏览 收藏

我在排查 Redis AOF rewrite 时最容易踩的坑,是把“Redis 已用内存没有明显上涨”和“磁盘还能写”当成同一件事。实际上,重写会 fork 子进程:子进程生成更紧凑的 AOF base 文件,主进程继续接收写入;写入越密集,COW(Copy-on-Write)页面和增量 AOF 写入就越值得警惕。

判断这段重写能不能继续,至少要同时看四件事:INFO persistence 的重写/COW 状态、INFO memory 的 RSS、文件系统剩余空间,以及 fsync 是否排队。used_memory 单独看不出完整风险。
要点速览
  • 内存重点看 current_cow_sizecurrent_cow_peakused_memory_rss 和系统可用内存的趋势。
  • 磁盘要把“空间不足”和“设备繁忙”分开处理,前者是硬阻断,后者通常先错峰或限流。
  • Redis 7.0+ 使用多部分 AOF,旧资料里的 aof_rewrite_buffer_length 已移除,不能再拿它做通用判断。

AOF rewrite 为什么会同时抬高内存和磁盘压力

重写不是把旧 AOF 原样复制一遍,而是根据当前数据集生成更短的 base 文件。Redis 通过 fork 创建后台子进程,主进程仍服务客户端。两者起初共享页面;主进程在重写期间修改某个页面时,操作系统才产生 COW 副本。因此风险与“重写时有多少数据被写到”有关,不只是数据集有多大。

在 Redis 7.0 及以后,主进程会继续写新的 incremental AOF,子进程负责生成 base AOF,最后通过清单原子切换。于是至少存在两类压力:COW 让进程 RSS 可能抬高,base/incremental 文件和 fsync 又会占用磁盘带宽与空间。

Redis AOF rewrite 中主进程、fork 子进程、COW 页面与 base 和 incremental 文件的静态关系
图1:AOF rewrite 的资源关系结构示意图;主进程继续接收写入,子进程生成 base 文件,写入同时影响 COW 页面与 incremental 文件。

先用 INFO persistence 看重写是否正在制造额外开销

第一组指标回答“现在是不是重写中,以及额外内存从哪里来”。可以定时采样下面的字段:

# 只读取重写状态和 COW 相关字段,不修改 Redis 配置
redis-cli INFO persistence | grep -E 'aof_rewrite_in_progress|aof_current_rewrite_time_sec|current_cow_size|current_cow_peak|aof_last_bgrewrite_status|aof_pending_bio_fsync'

aof_rewrite_in_progress:1 表示当前重写仍在进行;current_cow_size 是当前 COW 大小,current_cow_peak 用来观察本次运行中的峰值。重写结束后,再看 aof_last_cow_sizeaof_last_rewrite_time_secaof_last_bgrewrite_status,才能判断这次是否成功收尾。

如果是 Redis 7.0+,不要因为找不到 aof_rewrite_buffer_length 就认为采集失败。官方 INFO 文档明确说明该字段已移除,应改看 COW、AOF buffer 和 fsync 相关指标。

内存压力要对照 RSS、COW 和分配器碎片

used_memory 更接近 Redis 分配器已分配的内存,而 used_memory_rss 是操作系统看到的常驻集。重写期间,COW 页面可能让 RSS 先上涨;另外分配器碎片、客户端缓冲和 AOF 缓冲也会占用主机内存。

# 组合 Redis 内存、RSS、碎片和持久化状态,便于每秒采样比较趋势
redis-cli INFO memory | grep -E 'used_memory:|used_memory_rss:|mem_fragmentation_ratio:|allocator_rss_bytes:'
redis-cli MEMORY STATS

我的判断顺序是:先确认 current_cow_peak 是否持续增长,再看 used_memory_rss 是否逼近主机可用内存;最后用 MEMORY STATS 分辨 AOF、客户端和 allocator 的额外开销。系统可用内存快速下降、COW 峰值不断刷新时,应先降低重写窗口内的写入峰值或延后重写,而不是急着把 maxmemory 调到物理内存上限。

磁盘压力分成空间、吞吐和 fsync 排队

磁盘剩余空间是最硬的边界。先确认 AOF 目录所在挂载点,再看设备是否忙,以及 Redis 是否有待处理的 fsync:

# 路径替换为 appenddirname 对应的实际挂载点;这里只读系统状态
df -h /var/lib/redis
df -i /var/lib/redis
iostat -dx 1

# 查看 AOF 写入与 fsync 排队状态
redis-cli INFO persistence | grep -E 'aof_pending_bio_fsync|aof_delayed_fsync|aof_buffer_length|aof_current_size|aof_base_size'

空间不足时不要继续手工触发 BGREWRITEAOF;应先清理或扩容,并确认 AOF 目录中的 base、incremental 文件和 manifest 关系。设备利用率长期很高、aof_pending_bio_fsync 增长,则更像 I/O 饱和或 fsync 竞争,处理重点是错开备份、降低写入突发,或评估 no-appendfsync-on-rewrite

appendfsync everysec 通常是速度与持久性的折中。将 no-appendfsync-on-rewrite 设为 yes 可以减少重写时的 fsync 压力,但会改变故障时的数据持久化边界,不能把它当成无代价的性能开关。

用检查清单决定继续、错峰还是暂停

观察结果更可能的风险动作
空间接近运维下限新 AOF 文件无法完整落盘先扩容或释放空间,暂停手工重写
COW 峰值和 RSS 同时上升写入触发页面复制,内存峰值放大错开高写入窗口,给主机和 Redis 留余量
fsync 排队增长、设备长期繁忙持久化 I/O 竞争导致延迟错开备份和重写,评估 fsync 策略
重写完成且状态成功、曲线回落本次资源峰值已解除记录峰值,更新下次重写的容量预算

这里不建议写一个对所有实例都适用的“剩余百分比”。更可靠的边界是用历史峰值估算:数据集、COW 峰值、分配器碎片、客户端缓冲、AOF 文件增长和系统自身开销,都要留在同一台主机的可用资源内。重写完成后,确认 aof_rewrite_in_progress:0、最后状态成功、磁盘空间和延迟恢复,再关闭这次观察。

Redis AOF rewrite 诊断中 INFO persistence、INFO memory、MEMORY STATS 与主机资源共同指向运维动作的关系矩阵
图2:重写期间的观测矩阵结构示意图;Redis 内部指标与主机资源分别归组,最终共同指向运维判断。

相关问题

为什么 used_memory 没涨,机器内存却快满了?

因为 RSS 还包含 COW 页面、分配器驻留页和其他进程开销。重写期间应同时看 used_memory_rsscurrent_cow_peak 与系统可用内存。

Redis 7.0+ 还能看 aof_rewrite_buffer_length 吗?

不能把它当作通用指标。该字段在 Redis 7.0 被移除,改用 current_cow_*、AOF buffer 和 fsync 相关字段组合判断。

no-appendfsync-on-rewrite 应该一直设为 yes 吗?

不应该。它是降低重写期间 fsync 压力的取舍项,是否采用取决于磁盘延迟和可接受的数据持久化风险,必须在目标负载下压测并监控。

声明:本文转载于:17golang原创 如有侵犯,请联系study_golang@163.com删除
相关阅读
更多>
最新阅读
更多>
课程推荐
更多>