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)合并后的逻辑请求数,在带缓存、virtio、NVMe 多队列或 LVM 的环境里严重失真。只有加 -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 和普通 iostat 都算不准 IOPS
dd 本质是单线程顺序拷贝,它测的是大块连续 IO 下的吞吐(如 bs=1M),完全无法模拟随机小 IO 场景,也无法体现并发请求数——而 IOPS 正是为衡量后者设计的。
常见误用包括:
Linux 安全审计工具,检查 SSH 配置、开放/监听端口、防火墙规则(ufw/iptables/nftables)、失败登录尝试、sudoers 权限...
- 用
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共同决定并发压力,缺一不可 -
--rw=randread/--rw=randwrite明确指定随机模式,顺序模式(read/write)不反映典型 IOPS 场景 - 云环境(KVM/virtio)下,
fio在 guest 中测出的是下发到 virtio queue 的 IOPS,不是物理 SSD 的 NAND 操作次数
真实 IOPS 不是“算出来”的,而是由设备驱动直接上报的计数器值;iostat -x 是唯一能读到它的标准接口,其他任何推导都容易在现代存储栈中失真。最易被忽略的是:不结合 await 和 avgrq-sz 看 r_ios,等于只看半张牌。

















