用 iostat -xdm 1 查磁盘真实负载:重点关注 await(>10ms 警惕)、r/s/w/s 突增时结合 rkb/s/wkb/s 判断 io 模式;%util ssd 常虚高,hdd >60% 才需排查;设备名需与 lsblk 对齐,nvme 用 nvme0n1 等物理名。

怎么用 iostat 看出磁盘是不是真忙
iostat 默认只显示平均值,容易误判——比如 1 秒内突发 500 IOPS 后空闲 9 秒,平均才 50,但应用可能卡死在那 1 秒。必须加 -x(扩展指标)和 -d(跳过 CPU),再用 -t 指定间隔,比如:iostat -xdm 1。
重点关注三列:%util 高不代表磁盘瓶颈(SSD 下常虚高),await 超过 10ms 要警惕,r/s 和 w/s 突增时结合 rkB/s/wkB/s 判断是小包还是大块读写。
- 如果
await高但%util很低,可能是队列深度不够或上层限流(如 cgroup、qos) - SSD 上
%util接近 100% 很常见,别直接当成瓶颈;HDD 超过 60% 就该查了 -
iostat的设备名(如sda)要和lsblk对齐,LVM 或 NVMe 设备名(nvme0n1)不带分区号时才代表物理设备
iotop 显示的进程 I/O 为什么和实际不符
iotop 默认只统计“正在进行”的 I/O,不包含已提交到队列但未完成的请求,所以瞬时值波动大,且对 buffered write 不敏感——数据还在 page cache 里没落盘时,iotop 基本不显示。
启动时加 -o 只显示有 I/O 的进程,加 -P 按进程而非线程聚合,更实用。但要注意:
- 必须用 root 运行,否则看不到其他用户进程的 I/O
- 某些容器环境(如 runC)里,进程 PID 在宿主机命名空间中不可见,
iotop会漏掉 - 如果看到某进程
IO>0但磁盘整体iostat没动静,大概率是它在刷 cache(sync或fsync),还没真正发到底层
用 /proc/diskstats 自己算 IOPS 有什么坑
直接读 /proc/diskstats 是最轻量的方式,但字段顺序固定、无表头,第 4 列是读完成次数,第 8 列是写完成次数,第 3 列和第 7 列是合并请求数——很多人错把“读扇区数”(第 6 列)当成了字节数,其实得乘以 512。
脚本里取值前务必确认设备行位置,因为 md、dm-、loop 设备也会混在里面。建议用 awk '/sda$/ {print $4,$8}' /proc/diskstats 这种锚定行尾的方式,避免匹配到 sda1 分区。
- 同一设备在不同内核版本中字段数可能不同(比如新内核加了 discard 统计),硬编码列数易出错
- 数值是累加值,自己算差值时要注意采样间隔不能太短(
- RAID 卡直通模式下,
sda行反映的是卡逻辑盘,不是物理盘,想看真实盘得进卡管理界面或查/sys/block/<code>cciss!c0d0 这类路径
为什么 dd 测出来的吞吐量和线上业务差很远
dd if=/dev/zero of=test bs=1M count=1024 oflag=direct 测的是理想顺序写,而数据库、日志服务多是随机小 IO + sync,两者负载模型完全不同。
真实瓶颈往往不在磁盘本身,而在队列、文件系统或缓存策略:
-
oflag=direct绕过 page cache,但没关 write cache(硬盘或 RAID 卡上的),加conv=fdatasync才能强制刷盘,否则结果虚高 - 默认
dd用单线程,而生产环境常并发几十个 writer,得用parallel或fio模拟 - XFS 默认启用
allocsize=64k,小文件写可能触发反复分配,dd完全不触发这类路径
线上问题优先看 iostat -x 的 avgqu-sz(平均队列长度)和 svctm(服务时间),这两个比 dd 数字更能说明磁盘响应能力是否被压垮。











