vm.dirty_expire_centisecs / dirty_writeback_centisecs 导致脏页回写卡顿的调优

18次阅读

改了 vm.dirty_expire_centisecs 仍卡,因未同步调整 vm.dirty_writeback_centisecs;后者需 ≤ 前者(建议设为一半),否则过期脏页无法及时回写。

vm.dirty_expire_centisecs / dirty_writeback_centisecs 导致脏页回写卡顿的调优

为什么 改了 vm.dirty_expire_centisecs 还是卡?

这个参数控制脏页“过期时间”,单位是厘秒(centiseconds),默认 3000(即 30 秒)。但单纯调小它,比如设成 500(5 秒),并不一定减少卡顿——因为内核真正触发回写,还得看 vm.dirty_writeback_centisecs 是否及时唤醒回写线程。

常见错误是只调 dirty_expire_centisecs,却忽略 dirty_writeback_centisecs 的配合。后者默认 500(5 秒),表示内核每 5 秒唤醒一次 pdflush(或现代内核的 writeback 线程)去扫描过期脏页。如果它太长,即使页已过期,也得等下一轮扫描才开始写,造成延迟堆积。

  • vm.dirty_writeback_centisecs 应 ≤ vm.dirty_expire_centisecs,否则过期页可能滞留多个周期
  • 生产环境建议设为 dirty_expire_centisecs / 2 左右,例如 expire=1000,则 writeback=500
  • 值过小(如 writeback=100)会导致频繁唤醒线程,增加调度开销,尤其在高 I/O 负载下反而加剧抖动

vm.dirty_ratiovm.dirty_background_ratio 怎么配合 dirty 回写节奏?

这两个参数决定内存中脏页占比阈值,直接影响是否触发同步 / 异步回写,和上面两个时间参数共同构成“水位 + 时间”双控机制。

典型卡顿场景:应用突发写入大量数据,dirty_background_ratio(默认 10)很快被突破,内核启动后台回写;但如果磁盘慢,脏页持续累积,逼近 vm.dirty_ratio(默认 20),此时所有新写入线程会被阻塞,直到脏页降到 dirty_ratio 以下——这就是“卡住”的根源。

  • 若磁盘吞吐能力弱(如机械盘、高延迟云盘),适当降低 vm.dirty_background_ratio(如设为 5),让后台回写更早介入
  • vm.dirty_ratio 不建议低于 10,否则容易因瞬时写入波动就触发阻塞;也不建议高于 30,会显著拉高 OOM 风险
  • 注意:这些 ratio 是相对于 vm.lowmem_reserve_ratio 之外的可用内存计算的,不是总内存百分比

如何验证当前 dirty 回写是否真的成为瓶颈?

别猜,用 工具 看实际行为。关键指标不是“有没有脏页”,而是“脏页是否堆积 + 回写是否滞后”。

  • 查实时脏页状态:grep -i dirty /proc/meminfo,重点关注 Dirty:Writeback: 行。如果 Writeback 长时间 > 0 且 Dirty 持续上升,说明回写跟不上
  • 看内核日志是否有 writeback: balance_dirty_pages 相关 trace(需开启 echo 1 > /proc/sys/vm/block_dump 或用 perf),确认是否频繁进入阻塞路径
  • iostat -x 1 观察 %utilawait:若 await 突增且 Dirty 同步上涨,基本可定位为 dirty 回写压垮磁盘

SSD 和 NVMe 场景下要不要调?

要,但方向相反。SSD/NVMe 的随机写延迟低、并行度高,传统“保守延后写”的策略反而浪费性能。

默认的 30 秒过期时间对 SSD 来说太长,容易导致脏页批量冲刷,引发短时 I/O 尖峰。而 SSD 更适合细粒度、高频次的轻量回写。

  • 可将 vm.dirty_expire_centisecs 降至 500–1000(5–10 秒),vm.dirty_writeback_centisecs 设为 200–500(2–5 秒)
  • vm.dirty_background_ratio 可适度提高到 15,避免过早触发回写干扰前台 IO;但 vm.dirty_ratio 仍建议维持 20–25,防止内存耗尽
  • 注意:某些 NVMe 驱动或文件系统(如 XFS)对 writeback 线程并发数敏感,若调得太激进,可能触发 writeback: bdi-X: writeback timeout 类似错误

最易被忽略的是:这些参数在容器或 cgroup v2 环境下可能被覆盖,/sys/fs/cgroup/ 下的 memory.pressureio.pressure 才是更直接的信号源。

text=ZqhQzanResources