iostat -dx 1 是唯一能直接给出磁盘当前毫秒级延迟的命令,因其直接解析/proc/diskstats第11列(await累加值)与第4/8列(读写完成次数)实时计算平均延迟,提供r_await、w_await、aqu-sz等关键字段,单位毫秒,hdd超10ms、sata ssd超1ms、nvme超0.1ms即预警,且-d屏蔽cpu干扰、-x启用扩展指标,其他工具无法替代。

iostat -dx 1 是唯一能直接告诉你“磁盘当前延迟多少毫秒”的命令,其他工具要么间接、要么缺关键字段——不加 -x 的 iostat 基本等于没看。
为什么必须用 iostat -dx 1 看延迟
内核只通过 /proc/diskstats 暴露原始 I/O 计数器,iostat -dx 是唯一把其中第 11 列(await 累加值)和第 4/8 列(读写完成次数)实时算成毫秒级平均值的用户态工具。没有它,你得手动算:(await_sum / io_count) * 1000 / tick,而且还没法每秒刷新。
-
-d:屏蔽 CPU 行,避免干扰判断设备本身状态 -
-x:启用扩展字段,r_await、w_await、aqu-sz全靠它;不加就只有r/s和wkB/s,完全看不出卡在哪 - 单位全是毫秒(ms),不是微秒也不是纳秒——HDD 超
10、SATA SSD 超1、NVMe 超0.1就该动手查了 -
svctm字段在 Linux 5.0+ 已被废弃,别信;%util在 NVMe 上基本失效,别当真
iostat 输出里哪几列真正决定你今晚要不要加班
盯死这三行数字,别扫一眼就划走:
-
r_await和w_await:分开看。如果w_await是25而r_await是0.3,说明写路径卡死,立刻查日志刷盘、fsync 频率、journal 模式 -
aqu-sz(平均队列长度):持续 >1表示请求在排队,不是磁盘慢,是压太狠或调度器错配;值 >5且await同步涨,基本可断定块层已堵死 -
await:综合读写平均耗时,但它是“平均”,掩盖长尾。如果await=0.4却业务总超时,说明 p99.9 延迟爆了——这时候得切fio,不是继续刷iostat
看到高 await 却找不到罪魁祸首?这些地方常被跳过
iotop -o 会漏掉三类真实写盘行为,导致你盯着屏幕怀疑人生:
- 短时高频小 I/O:比如 Node.js 进程每秒发 2000 次
write(2),iotop默认 1 秒采样一次,可能只捕获到 1–2 次,显示 IO% = 0.1% - mmap + msync 或脏页自动回写:数据走 page cache → bdi flush 线程,
iotop显示的是kswapd0或ksmd,不是你的应用进程 - 管道/套接字间接落盘:如
nginx → syslog-ng → /var/log/messages,iotop只标出syslog-ng,源头藏得深 - 真找不到进程?直接看
cat /proc/diskstats第 9 列(aveq)和第 11 列(await累加值),前后 5 秒对比是否真在堆积;再查cat /sys/block/nvme0n1/queue/scheduler,NVMe 设备必须是none,若显示bfq就是调度器被错误启用
ioping 和 fio 不是日常监控项,是确诊用的“CT 扫描”
当你发现 iostat 里 await 波动剧烈(比如 avg=0.3ms,但某次刷出 18ms),说明存在长尾抖动,这时:
- 用
ioping -C -c 10 /dev/nvme0n1直打裸设备:加-C强制同步落盘,排除 page cache 干扰;avg 超0.2ms 就得查 PCIe 链路、NVMe 固件或驱动 - 用
fio提取百分位延迟:配置必须含direct=1、iodepth=32、runtime=60,否则测的是缓存速度;重点看clat_ns下的p99.9,不是 avg - 别用
dd测延迟:dd if=/dev/zero of=test bs=1M count=1024 oflag=direct只反映顺序大块吞吐上限,完全不模拟真实业务的随机小 IO 场景
最常被忽略的一点:await 高 ≠ 磁盘坏了。它可能只是内核在等一个还没触发的 fsync,或某个进程卡在 write 返回前,而 iotop 根本抓不到那一帧。











