问题出现得很突然,日志倒是留得挺全。一台 8G 内存的 CentOS 7.9 跑批处理,vmstat 1 里 bo 长期在 20000 以上,bi 几乎为 0,wa 只占 5%,但任务的实际耗时比昨天多了一倍,iostat 里磁盘 util 不到 20%。

刚开始盯着「有文件被 mmap 后持续改写,内核定期回刷脏页」,折腾了半个多小时,排掉了。

排查方向其实有限,先把可能性排一排。bo 统计的是提交给块设备的写,落到 RAID 卡缓存后才算完成。也可能是内存回收在频繁写回脏页,实际写放大比业务量大得多。

还有一种情况,云盘的写缓存把延迟藏住了,真正瓶颈在队列深度。

动手时先分清是业务写还是脏页回刷

vmstat 1 5 && grep -E 'nr_dirty|nr_writeback' /proc/vmstat

接着看具体哪个进程在写

iotop -o -b -n 2 | head -20

然后确认脏页阈值和回刷间隔

sysctl vm.dirty_ratio vm.dirty_background_ratio vm.dirty_expire_centisecs

剩下的就是按需收紧脏页比例减少抖动

sysctl -w vm.dirty_background_ratio=5 vm.dirty_ratio=10

改完先别撤,确认这几项。bo 回落到业务实际写入量附近,批处理耗时回到昨天的水平,vmstat 里的 wa 稳定在 2% 以内。

bo 高不等于磁盘慢,先看 nr_dirty 和设备队列;调脏页比例会影响突发写入的吸收能力,改完要观察一整天的曲线。监控比日志更早给出信号,事后回看经常能提前半小时发现异常。

作者 9823189