问题出现得很突然,日志倒是留得挺全。一台 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 和设备队列;调脏页比例会影响突发写入的吸收能力,改完要观察一整天的曲线。监控比日志更早给出信号,事后回看经常能提前半小时发现异常。
