iostat -dx 1 判断磁盘真饱和需联动分析:await >30ms 且 avgqu-sz >8(NVMe)或 >4(SSD)表明真实I/O瓶颈;高 await 低 %util 指向内核或文件系统问题,而非磁盘物理能力不足。

iostat -dx 1 是设备级 IO 监控的起点,但单看 %util 容易误判饱和——必须结合 avgqu-sz 和 await 才能判断真实瓶颈。
iostat -dx 1 怎么读出磁盘是否真饱和
很多人看到 %util 接近 100% 就认定磁盘卡死,其实 HDD 和 SSD 对队列深度容忍差异很大,单靠这一项会漏掉早期延迟问题:
-
%util长期 >80% 是危险信号,但若avgqu-sz始终 -
r_await或w_await>20ms 且持续上升,比%util更早暴露响应延迟瓶颈 - 用
iostat -xk 1 /dev/sdb可聚焦某块盘;加-p ALL(如iostat -xk 1 -p ALL)能看见 LVM 逻辑卷和分区拆分数据 -
iostat -dx 1中的-d已隐含“只看磁盘”,避免默认混入 CPU 行干扰判断
iotop -o 为什么总看不到高 IO 进程
常见现象是启动后一片空白,或只显示几个内核线程——不是没 IO,而是权限或过滤逻辑导致:
- 必须用
sudo iotop -o,非 root 用户无法读取/proc/*/io,会静默跳过所有用户进程 -
-o只显示“当前有 IO 活动”的进程;某进程刚刷完一批日志、正空闲,就不会出现;临时去掉-o可看全量,但噪音大 - 容器或 systemd 服务在 cgroup v2 下可能被归为统一 IO 组,
iotop显示的是宿主机视角,不反映容器实际限制后的用量 - 快捷键
O(Shift+o)按 IO 带宽降序,p切换 PID/TID 显示,避免被线程 ID 搞混
pidstat -d 1 如何精准监控某个服务的 IO 速率
想盯住 nginx 或 Java 进程的实时读写速度,pidstat -d 最直接,但参数错一步就白忙:
- 必须带采样间隔,如
pidstat -d 1;只输pidstat -d执行完立刻退出,看不到动态变化 - 别用
pidstat -d 0,这会让内核疯狂采样,终端卡死甚至触发 OOM - 用
pgrep -f定位 PID 最可靠:pidstat -d 2 -p "$(pgrep -f 'java.*-Dspring')",比ps aux | grep抗干扰强 - 输出中只认
rkB/s和wkB/s两列——它们是真实瞬时速率(KB/s),其他如%MEM或RSS是内存字段,跟 IO 无关 - 如果
rkB/s在 0 和 15000 之间剧烈跳变,大概率是应用用了 buffered I/O + 小批量刷盘,不是硬件问题
dd iflag=direct 测试结果为什么和 iostat 看到的不一致
用 dd if=/dev/zero of=testfile bs=1M count=1024 oflag=direct 测出 300MB/s,但 iostat 显示 wkB/s 只有 50MB/s?这不是工具不准,而是测量对象根本不同:
-
dd测的是单次大块顺序写吞吐,绕过缓存直写设备,反映的是磁盘理论峰值 -
iostat统计的是系统运行中所有进程的真实混合 IO,含随机小 IO、元数据操作、队列等待等,反映的是实际负载下的表现 - 两者数值差异大很正常;若
dd结果也远低于标称值(如 SSD 写不到 300MB/s),才需怀疑驱动、队列深度或硬件链路问题
真正难的是把三者串起来:先用 iostat -dx 1 锁定设备异常,再用 iotop -o 找出活跃进程,最后用 pidstat -d 持续验证该进程行为。中间任何一环断开,就容易把延迟归因于错误层级。


















