iostat -dx 1是诊断磁盘i/o瓶颈的起点,它直接解析内核/proc/diskstats原始数据:-d只显示磁盘指标,-x启用r_await/w_await等关键延迟字段,单位毫秒,hdd超10ms、nvme超0.5ms即预警,aqu-sz持续>1表明请求排队而非设备慢。

直接看结论:别堆工具,先跑 iostat -dx 1,它能告诉你磁盘是不是真卡了——其他监控都是在这基础上补细节。
iostat -dx 1 是什么,为什么必须从它开始
这不是“又一个监控命令”,而是内核暴露的原始 I/O 状态快照。所有上层工具(包括 Zabbix、Prometheus 的 node_exporter)最终都读 /proc/diskstats,而 iostat -dx 1 就是把那堆数字翻译成人话的最简接口。
-
-d表示只看磁盘,不混 CPU 行干扰判断 -
-x开启扩展模式,r_await和w_await才真正有用;%util在 NVMe 上基本失效,svctm已被内核废弃 - 数值单位全是毫秒(ms),HDD 超 10ms、SATA SSD 超 1ms、NVMe 超 0.5ms 就该警觉
- 关键要看
aqu-sz(平均队列长度):持续 >1 表示请求在排队,不是设备慢,是压太狠
怎么用 iotop 定位“谁在拖慢磁盘”
iotop 不是万能,但它是连接设备延迟和进程行为的唯一桥梁——前提是用对参数。
- 必须加
sudo iotop -o:非 root 无法读/proc/*/io,否则只显示内核线程,用户进程全消失 -
-o只显示当前有 I/O 活动的进程,适合抓“正在写”的瞬间;如果想看全量(含休眠中刚刷完脏页的 Java 进程),去掉-o,再按O(Shift+O)按 IO 带宽排序 - 别信
IO%列:它是相对占比,不是绝对吞吐;优先盯DISK READ和DISK WRITE的 KB/s 数值 - 看到
mysqld占高?立刻lsof -p $(pgrep mysqld)查它在读哪个文件,再cat /proc/$(pgrep mysqld)/io对比read_bytes和rchar——差太多说明卡在 page cache,不是磁盘本身
什么时候该上 fio 或 ioping,而不是继续盯着 iostat
iostat 告诉你“有问题”,fio 和 ioping 告诉你“问题在哪一层”。它们不是日常监控项,而是诊断触发器。
- 当
r_await波动剧烈、p99 延迟远高于 avg(比如 avg=0.3ms,p99.9=12ms),说明存在长尾抖动:fio是唯一能打出百分位延迟分布的工具。配置里必须设direct=1、runtime=60、iodepth=32,否则测的是缓存速度 - 当怀疑是裸设备层问题(比如 RAID 卡、NVMe 控制器固件异常),绕过文件系统直打设备:
ioping -C -c 10 /dev/nvme0n1。加-C强制同步落盘,排除缓存干扰;avg超 0.2ms 就得查硬件或驱动 - 别用
dd测延迟:dd if=/dev/zero of=test bs=1M count=1024 oflag=direct只反映顺序大块吞吐上限,完全不模拟真实业务的随机小 IO 场景
自定义脚本或 Zabbix 监控时最容易踩的坑
所有基于 /proc/diskstats 的二次开发,都绕不开扇区换算和状态缓存——错一点,指标就全歪。
-
/proc/diskstats第 6 列(读扇区数)和第 10 列(写扇区数)单位是 512 字节扇区,不是字节。换算成 KB 要 ×0.5,不是 ÷1024 - 计算每秒速率必须做两次采样差值,并记录时间戳;简单
sleep 1不可靠,高负载下可能 drift 几百毫秒,导致r_await计算失真 - Zabbix 自定义 key 中的
grep sd[a-z]+会漏掉nvme0n1p1这类设备名,得改成grep -E "(sd[a-z]|nvme[0-9]+n[0-9]+p?[0-9]*)" - 别依赖
%util做告警阈值:NVMe 多队列设备上,%util=95%可能只是单个队列忙,实际并发能力还有余量;改用aqu-sz > 2+w_await > 1组合更稳
真正难的不是采集数据,而是区分“设备慢”和“请求太猛”——aqu-sz 和 r_await 的比值关系,比任何单点数值都关键。这点很容易被忽略,但它决定你是调优还是扩容。











