iostat —— 磁盘 IO 与 CPU 概览(定位 iowait 瓶颈)
这个工具是做什么的
sysstat 套件成员。当 top/vmstat 显示 wa(iowait) 高、b 队列大时,用 iostat 确认是哪块盘、多忙、延迟多高、是随机小 IO 还是顺序大 IO。它到设备级,落到进程还需 iotop/pidstat -d。
可以回答什么问题
| 问题 | 怎么用 |
|---|---|
| 是哪块磁盘在忙? | iostat -x 1 按设备看 %util 和 await |
| 磁盘 IO 延迟高不高? | r_await/w_await 列(单位 ms) |
| 是随机小 IO 还是顺序大 IO? | rareq-sz/wareq-sz:几 KB = 随机,几百 KB = 顺序 |
| IOPS 多少?吞吐量多少? | r/s/w/s = IOPS,rkB/s/wkB/s = 吞吐 |
| SSD/NVMe 真的到瓶颈了吗? | 别看 %util,看 await 和 aqu-sz(%util 在多队列盘上会失真) |
数据来源
- 来源文件:每个块设备的读写次数、扇区数、IO 耗时、队列时间取自
/proc/diskstats(等价/sys/block/*/stat);顶部 CPU 行取自/proc/stat。 - 采集方式:按间隔读两次这些累计计数,做差算出 IOPS(
r/s/w/s)、吞吐(kB/s)、延迟(await)、%util等。 - 由此决定的特性:数据到设备级为止,看不到"哪个进程在读写"——要落到进程得配 iotop 或
pidstat -d;且%util在能并行处理请求的 SSD/NVMe 上会失真(见正文的坑)。
yum install sysstat / apt install sysstat一、用法
iostat # 一次性:CPU 汇总 + 各设备开机以来平均
iostat 1 # 每 1 秒刷新(CPU 行 + 设备行)
iostat -x 1 # 扩展模式(最常用,含 %util、await 等关键列)
iostat -xd 1 # -d 只看磁盘,不显示 CPU 行
iostat -xm 1 # -m 单位用 MB/s(默认 KB/s 或块)
iostat -x 1 sda nvme0n1 # 只看指定设备
iostat -xh 1 # -h 人类可读、每设备纵向排列(新版,宽表看不过来时好用)
iostat -xp 1 # -p 展开到分区级(sda1、sda2...)第一行是开机以来平均,看第二行起的实时值。
二、-x 扩展模式字段全解
Device r/s w/s rkB/s wkB/s rrqm/s wrqm/s r_await w_await aqu-sz rareq-sz wareq-sz %util
sda 12.0 340.0 192.0 43520.0 0.0 15.0 0.30 8.50 2.90 16.0 128.0 96.20| 字段 | 含义 | 判读 |
|---|---|---|
r/s w/s | 每秒完成的读/写请求数(IOPS) | |
rkB/s wkB/s | 每秒读/写 KB(吞吐) | |
rrqm/s wrqm/s | 每秒被内核合并的读/写请求数 | 合并多 = 有相邻请求被攒着一起下发(顺序 IO 特征) |
r_await w_await | 读/写平均延迟(ms,含排队+服务时间) | 最关键。机械盘正常个位数~十几 ms,SSD 应 <1ms;偏高 = 盘慢或在排队 |
aqu-sz | 平均队列深度(旧版 avgqu-sz) | >1 且持续 = 请求在排队等设备 |
rareq-sz wareq-sz | 平均每次请求大小 KB | 小(几 KB)= 随机小 IO,效率低;大(几百 KB)= 顺序大 IO |
%util | 设备繁忙时间占比 | 见下方坑 |
三、判断口诀
| 现象 | 结论 |
|---|---|
%util 接近 100% + await 高 | 磁盘打满,是瓶颈 |
await 高但 %util 不高 | 单次请求太大、或后端存储(网络盘/RAID)慢 |
r/s/w/s 很高但 rareq-sz 很小 | 大量随机小 IO → 合并写、加缓冲、换 SSD |
只有 kB/s 高、await 正常 | 顺序大 IO,通常健康(如备份、大文件拷贝) |
w_await 远大于 r_await | 写瓶颈(如频繁 fsync、日志刷盘) |
四、%util 的重要陷阱
%util = 设备至少有一个请求在处理的时间占比。
- 机械盘(单队列):
%util接近 100% 基本等于打满,参考意义大。 - SSD/NVMe(多队列、可并行):能同时处理几十上百个请求,
%util到 100% 也不代表真的满了——它只表示"一直有活干",不代表并行度用尽。判断 NVMe 是否到瓶颈要看await是否随负载明显上升、aqu-sz是否堆积,而非只看%util。
五、结合本仓库与定位到进程
./cpu_demo & # 选场景 2(狂写 /tmp 文件)
iostat -x 1 # 观察对应盘的 w/s、wkB/s、w_await 上升
# 确认哪块盘忙后,落到进程:
pidstat -d 1 # 看 kB_wr/s 最高的进程
sudo iotop -o # 或交互式直接看标准排查链:top/vmstat 见 wa 高 → iostat -x 1 定位哪块盘、是随机还是顺序、延迟多少 → iotop/pidstat -d 找到罪魁进程 → strace -e trace=read,write,fsync -p <PID> 看它在读写什么、多频繁。
六、关键指标速查
| 指标 | 缩写/英文 | 参考值(按设备类型) | 异常信号 |
|---|---|---|---|
| 读/写 IOPS | r/s w/s / Read/Write IOPS | HDD: 100-200, SATA SSD: 50K-100K, NVMe: 500K-1M | 接近/超过设备规格上限 |
| 读/写吞吐 | rkB/s wkB/s / Throughput | HDD: 150-250 MB/s, SATA SSD: 500-550 MB/s, NVMe: 3000-7000 MB/s | 接近设备带宽上限 |
| 平均延迟 | await / Avg Wait Time | HDD: 5-20ms, SATA SSD: 0.05-0.5ms, NVMe: 0.01-0.1ms, Optane: <0.01ms | 持续高于参考值 → 盘慢或排队 |
| 读延迟 | r_await / Read Latency | 同上 | 远高于写 → 读密集型瓶颈 |
| 写延迟 | w_await / Write Latency | 同上 | 远高于读 → 写拥塞/频繁 fsync |
| 平均队列深度 | aqu-sz / Avg Queue Size | HDD: <2, SSD: 可 >4(多队列盘正常) | HDD > 2 且持续 → 堆积;NVMe > 32 且 await 不升 → 盘有余力 |
| 设备占用率 | %util / Device Utilization | — | 机械盘近 100% → 打满;SSD/NVMe 不可信(看 await+aqu-sz) |
| 平均请求大小 | rareq-sz wareq-sz / Avg Req Size | 4K-64K(随机小 IO),128K-1M(顺序大 IO) | 几 KB → 随机小 IO,效率低;几百 KB → 顺序大 IO,健康 |
| 合并请求数 | rrqm/s wrqm/s / Merge Rate | 有合并=正常 | 合并不多 → 应用在发大量零散 IO |
| CPU iowait | %iowait | < 5% | > 20% → IO 是瓶颈(但 SSD/NVMe 上 iowait 容易虚高,配合 await 判断) |
IOPS/吞吐/延迟速记:HDD → ~200 IOPS / ~200 MB/s / ~10ms · SATA SSD → ~100K IOPS / ~500 MB/s / ~0.1ms · NVMe Gen4 → ~1M IOPS / ~6GB/s / ~0.02ms。跨三个数量级,
iostat -x 1的r/s、rkB/s、await对号入座。
七、常见排查方法与分析
7.1 await 高 → 确认是盘慢还是排队
iostat -x 1 → await 持续高
→ 同时看 aqu-sz:
→ aqu-sz > 2 → IO 请求在排队(盘处理不过来)
→ aqu-sz < 1 但 await 高 → 单次请求太大/后端存储慢
→ 看 r_await 和 w_await 分拆 → 读瓶颈还是写瓶颈7.2 随机小 IO vs 顺序大 IO
iostat -x 1 → rareq-sz / wareq-sz
→ 几 KB 且 r/s 很高 → 随机小 IO(效率低)
→ 合并写、加缓冲、换 SSD
→ 几百 KB 且 await 正常 → 顺序大 IO(通常健康)7.3 SSD/NVMe 瓶颈判断(不看 %util)
iostat -xdm 1 /dev/nvme0n1 → 关注 await 和 aqu-sz
→ %util 可能一直接近 100%(SSD/NVMe 多队列,此指标失真)
→ 真正瓶颈看:
→ await 是否随负载增加而明显上升
→ aqu-sz 是否持续堆积
→ r/s + w/s 是否接近盘规格上限7.4 写拥塞定位
iostat -x 1 → w_await >> r_await
→ iotop -o → 找 DISK WRITE 最高的进程
→ strace -e trace=write,fsync -p <PID> → 是否频繁 fsync
→ 频繁 fsync → 考虑异步写入或批量提交八、交叉引用
- IO 瓶颈入口:top
wa列 → vmstatb列 - 进程级 IO:iotop(哪个进程在读写)→ pidstat
-d(无 root 替代) - 系统调用追踪:strace(看进程在做什么文件操作)
- 数据源:procfs §三(/proc/diskstats 是 iostat 的数据来源)
- IO 调度器调优:kernel-tuning §二(/sys/block/.../queue/scheduler)
九、CPU 行
iostat 顶部还有一行 CPU:%user %nice %system %iowait %steal %idle,含义同 top。其中 %iowait 是判断"CPU 是不是在干等 IO"的入口指标。
总结
iostat 是磁盘/IO 瓶颈的入口工具:iostat -xdm 1 看扩展指标,核心是 await(IO 平均等待时间,含排队,高=盘扛不住)、%util(设备繁忙度,机械盘近 100% 即饱和,但 SSD/NVMe 多队列下失真)、aqu-sz(平均队列长度,持续堆积=拥塞);定位顺序还是随机看 IO 大小与 r/s(几 KB 且 r/s 高=随机小 IO,几百 KB 且 await 正常=顺序大 IO),写拥塞看 w_await 后用 iotop/pidstat -d 找进程、strace 查频繁 fsync,顶部 CPU 行的 %iowait 是「CPU 在干等 IO」的入口信号。