%wa高说明CPU大量时间等待IO完成,反映IO阻塞而非必然磁盘慢;需结合iostat、iotop等工具定位具体瓶颈点。

top 里 %wa 值高说明什么
%wa 是 top 中显示的 CPU 等待 IO 完成的时间百分比。它高 ≠ 磁盘慢,只说明有大量线程在阻塞等待 IO(比如读写文件、刷脏页、等待 NFS 响应)。真正瓶颈可能在磁盘本身,也可能在内核 IO 调度、文件系统层、甚至远程存储网络。
常见误判:看到 %wa > 30% 就断定是磁盘坏了——其实可能是某个进程反复 fsync()、日志刷盘太频繁,或 ext4 的 journal 模式配置不当。
- 若
%wa高但%sy(内核态 CPU)也同步飙升,大概率是内核路径争用(如大量小文件 write + sync) - 若
%wa高而%us(用户态 CPU)很低,说明应用基本没在计算,纯卡在 IO 上 -
top不区分读/写、不显示具体设备,必须配合iostat或iotop进一步下钻
iostat -x 1 看哪些指标最关键
运行 iostat -x 1 后重点关注三列:%util、await、svctm(已弃用,忽略)和 r/s/w/s。其中:
-
%util接近 100% 表示该设备几乎一直在忙,但注意:NVMe 多队列设备下这个值参考价值下降,需看avgqu-sz(平均队列深度)是否持续 > 1 -
await是单次 IO 平均耗时(毫秒),> 50ms 对 SATA 盘已偏高,> 10ms 对 NVMe 就值得查——但它包含排队时间,不能直接等同于磁盘响应慢 - 对比
r_await和w_await可快速判断是读还是写拖慢;若w_await显著更高,检查vm.dirty_ratio是否设得过大,导致刷盘风暴
示例异常输出:
iostat -x 1这里
sda 0.00 21.00 0.00 689.00 0.00 7345.00 21.42 100.00 145.12 145.12 0.00
await=145.12、%util=100.00,且 avgqu-sz=21.42,说明请求严重积压。
用 iotop 找出吃 IO 的进程
iotop 是实时定位罪魁进程最直接的工具,但默认不显示线程级 IO(尤其 Java 应用常有多个线程共用一个文件描述符)。启动时加 -P 查看进程汇总,加 -o 只显示有 IO 活动的条目,加 -a 累计 IO 量更准。
- 注意看
IO>列(当前瞬时写入速率)和IO列(累计总写入量),后者对识别“缓慢但持久”的后台任务(如 rsync、logrotate)更有用 - 如果看到
java进程 IO 很高,别急着 kill,先用lsof -p PID查它打开的文件,重点看logs/、/tmp、mapped files(内存映射大文件读写也会计入 IO) - 某些数据库(如 MySQL)的
innodb_io_capacity设置远低于磁盘实际能力,会导致大量 IO 被人为节流,此时iotop看到的是“被压低的 IO”,而非真实瓶颈
排查 ext4/xfs 文件系统层延迟
即使磁盘硬件正常,文件系统配置不当也会放大 IO 延迟。ext4 默认启用 barrier=1 和 journal=ordered,在无电池保护的 RAID 卡上会强制落盘,极大拖慢写性能。
- 检查挂载参数:
mount | grep ' / '`,留意是否有barrier=0(不推荐关)、data=writeback(降低 journal 开销,但崩溃可能丢数据) - 对 xfs,关注
xfs_info输出中的logbsize和logbufs,过小的日志缓冲区(如logbsize=4k)会导致频繁刷日志 - 临时验证:用
dd if=/dev/zero of=/tmp/test bs=4M count=1000 oflag=direct测裸写速度,若远低于磁盘标称值,问题大概率在文件系统或驱动层
真正难定位的往往是混合场景:比如 PostgreSQL 在 checkpoint 期间触发大量脏页回写,同时应用又在高频小事务提交,两者叠加让 await 突增,但单独看任一环节都“看似正常”。这时候得结合 pidstat -d 1 和 perf record -e block:block_rq_issue,block:block_rq_complete -a sleep 10 抓块层事件链。










