iostat -x 是唯一能看真实 iops 的命令,其 r_ios 和 w_ios 字段反映真正下发到设备的读写请求数,而普通 iostat 的 r/s、w/s 是合并后的逻辑请求,严重失真。

iostat -x 是唯一能看真实 IOPS 的命令
普通 iostat 显示的 r/s 和 w/s 不是真实 IOPS,它们是上层 IO 栈(VFS、block layer)合并、重排后的逻辑请求数,在 NVMe、virtio、多路径或带缓存的环境中严重失真。只有加 -x 选项后输出的 r_ios(读 I/O 次数)和 w_ios(写 I/O 次数)才代表真正下发到设备或 virtio queue 的请求个数——这才是你该信的 IOPS。
执行以下命令获取每秒真实读写次数:
iostat -dx 1 3
重点关注字段:
-
r_ios和w_ios:单位是次/秒,即真实读/写 IOPS -
rMB/s和wMB/s:绕过 page cache 的真实吞吐,单位 MB/s -
%util:仅对传统 HDD 有参考价值;NVMe 多队列下接近 100% 并不意味着瓶颈 -
await:平均等待毫秒,若持续 >10ms 且%util高,说明队列积压而非磁盘本身慢
为什么 dd 测不出 IOPS,只能测吞吐
dd 本质是单线程顺序拷贝,它反映的是大块连续 IO 下的吞吐能力(如 bs=1M),完全无法模拟随机小 IO 场景,也无法体现并发请求数——而 IOPS 正是为衡量后者设计的。
常见误用:
- 用
dd if=/dev/zero of=test bs=4k count=100000算“4K 随机写 IOPS”:错,这是顺序写,且未绕过缓存 - 看
dd输出的 123 MB/s 就认为 IOPS 很高:吞吐高 ≠ IOPS 高,比如 123 MB/s ÷ 4 KB = ~31.5K IOPS,但实际dd根本没发出那么多请求 - 忽略
oflag=direct或iflag=direct:不加这个,数据走 page cache,测的是内存速度,不是磁盘真实 IOPS
定位高 IOPS 来源必须配合 iotop 或 pidstat
iostat -x 只告诉你“设备忙”,不告诉你“谁在刷盘”。当 r_ios 或 w_ios 异常飙升时,需立刻查进程:
- 实时查看 TOP IO 进程:
sudo iotop -oP(只显示实际在做 IO 的进程,-P表示忽略线程) - 按秒采样并统计:
pidstat -d 1,关注rkB/s和wkB/s列,换算成 IOPS 要除以平均 IO 大小(如 4K → ÷4) - 注意:
iotop显示的 “DISK READ/WRITE” 是带缓存的速率,不能直接当 IOPS;它只是帮你快速锁定嫌疑进程
FIO 才是测可控 IOPS 的正确工具
如果要验证某块盘在特定负载下的稳定 IOPS(比如 4K 随机读 50K IOPS),iostat 是观测手段,fio 才是施压工具。它能精确控制 IO 类型、大小、队列深度、线程数。
例如测试裸设备 /dev/vdc 的 4K 随机读 IOPS:
fio --name=randread --ioengine=libaio --rw=randread --bs=4k --numjobs=4 --iodepth=128 --direct=1 --runtime=60 --filename=/dev/vdc
关键点:
-
--direct=1必须加,否则走 page cache -
--iodepth和--numjobs共同决定并发压力,太低测不出上限,太高可能触发限流或超时 - 真实业务是混合读写+随机/顺序混合,单测 randread/randwrite 只是基线,建议加
--rwmixread=70模拟典型负载
真实 IOPS 值取决于 IO 大小、队列深度、介质类型和驱动栈,同一块 NVMe 盘在不同 bs 和 iodepth 下结果可差 10 倍——别只记一个数字,要看场景。











