直接结论:调优 dirty_background_ratio 和 dirty_ratio 必须同步配置 dirty_expire_centisecs 与 dirty_writeback_centisecs,否则 write() 可能因前台强制刷脏页而卡顿数秒;其触发条件是脏页占可用内存(memfree + cached - mapped)比例达 dirty_ratio,此时所有 write() 同步阻塞,直至脏页回落。

直接结论:别只调 dirty_background_ratio 和 dirty_ratio,必须同步看 dirty_expire_centisecs 和 dirty_writeback_centisecs,否则调了也白调,甚至更卡。
为什么 write() 会突然卡住几秒?
这不是磁盘慢,而是内核在前台强制刷脏页:当脏页占比达到 dirty_ratio 时,所有新 write() 调用会被同步阻塞,直到脏页降到阈值以下。现象是日志里出现大量 write() blocked for N seconds,iostat -x 1 显示 %util 爆到 100、await 超过 50ms,但磁盘本身没坏。
- 触发条件不是“写了多少字节”,而是“脏页占可用内存(
MemFree + Cached - Mapped)的比例” -
dirty_ratio必须严格大于dirty_background_ratio,否则后台线程压根不启动,全靠前台硬扛 - 默认值(如 background=10, ratio=20)在 64G+ 内存机器上极易积压——后台刚唤醒,脏页又涨上来了
怎么设 dirty_background_ratio 和 dirty_ratio?
不能拍脑袋定百分比,得按写入节奏和磁盘能力来配:
Zynq‑7000 / Zynq UltraScale+ 硬件调试技能。适用于 Xilinx Zynq(Cortex‑A9/A53 + FPGA)Linux 环境,调试 I2C、I2S、UART、GPIO 等外设。包括设备树配置、内核驱动、用户空间调试工具、交叉编译和常见问题排查,支持 PetaLinux 开发。
- SSD/NVMe 高吞吐场景(如 Kafka、ClickHouse ingest):
dirty_background_ratio=5,dirty_ratio=12—— 让后台早点动手,避免单次刷几十 GB - 低延迟敏感服务(如金融行情写入):
dirty_background_ratio=3,dirty_ratio=8,再配dirty_expire_centisecs=1000(10 秒老化),不让脏页活过一拍 - 混合负载起步保守值:
dirty_background_ratio=10,dirty_ratio=15,之后盯/proc/vmstat的pgpgout和iostat -x 1的await变化 - 绝对不要设
dirty_ratio > 25:单次刷盘数据量过大,可能把 NVMe 的队列打满,引发秒级 I/O stall
dirty_expire_centisecs 和 dirty_writeback_centisecs 怎么配合?
这两个参数决定“脏页多老才刷”和“多久检查一次”,单独调一个等于白干:
-
dirty_expire_centisecs默认 3000(30 秒),对高写入服务太长——设成1000(10 秒)可防老化页堆积;但别低于500(5 秒),否则频繁唤醒刷小批量,反增 CPU 开销 -
dirty_writeback_centisecs默认 500(5 秒),大内存机器建议缩到100~200(1~2 秒)——让后台线程更勤快,把刷盘动作摊薄 - 如果
dirty_expire_centisecs设得太小(如 200),而dirty_writeback_centisecs太大(如 1000),会出现“过期了却没人来刷”的空等 - 验证是否生效:改完后运行
grep -i "flush\|writeback" /proc/sched_debug,看后台线程唤醒间隔是否变短
最容易被忽略的坑
很多人调完就以为搞定,结果线上还是卡——问题常出在三个地方:
- 用
echo 5 > /proc/sys/vm/dirty_background_ratio临时改完,没写进/etc/sysctl.conf,重启就回滚 - 误以为
dirty_ratio是占总内存比例,其实它和dirty_background_ratio一样,分母是“可用内存”,不是MemTotal - 忘了关掉
vm.dirty_bytes和vm.dirty_background_bytes:只要它们非零,对应 ratio 参数就自动失效,得先清零再设 ratio - 没观察
/proc/vmstat中的pgpgout(每秒刷盘页数)和pgmajfault(主缺页)联动——如果刷盘激增的同时 major fault 也跳,说明 page cache 挤占了应用内存










