iostat

发布时间: 更新时间: 总字数:2744 阅读时间:6m 作者: IP上海 分享 网址

iostat Report Central Processing Unit (CPU) statistics and input/output statistics for devices and partitions.

Help

# iostat --help
Usage: iostat [ options ] [ <interval> [ <count> ] ]
Options are:
[ -c ] [ -d ] [ -h ] [ -k | -m ] [ -N ] [ -t ] [ -V ] [ -x ] [ -y ] [ -z ]
[ -j { ID | LABEL | PATH | UUID | ... } ]
[ [ -T ] -g <group_name> ] [ -p [ <device> [,...] | ALL ] ]
[ <device> [...] | ALL ]

参数

  • -c 显示 CPU 使用情况
  • -d 显示磁盘使用情况
  • -k 以 KB 为单位显示
  • -m 以 M 为单位显示
  • -N 显示磁盘阵列(LVM) 信息
  • -n 显示 NFS 使用情况
  • -p [磁盘] 显示磁盘和分区的情况
  • -t 显示终端和 CPU 的信息
  • -x 显示详细信息
  • -V 显示版本信息

属性说明

  • cpu 属性说明
  • %user:CPU 处在用户模式下的时间百分比
  • %nice:CPU 处在带 NICE 值的用户模式下的时间百分比
  • %system:CPU 处在系统模式下的时间百分比
  • %iowait:CPU 等待输入输出完成时间的百分比
  • %steal:管理程序维护另一个虚拟处理器时,虚拟 CPU 的无意识等待时间百分比
  • %idle:CPU 空闲时间百分比

经验说明:

  • %iowait值过高,表示硬盘存在 I/O 瓶颈
  • %idle值过高,表示 CPU 较空闲,如果%idle值高但系统响应慢时,有可能是CPU等待分配内存,此时应加大内存容量
  • disk 属性说明
  • rrqm/s: 每秒进行 merge 的读操作数目。即 rmerge/s
  • wrqm/s: 每秒进行 merge 的写操作数目。即 wmerge/s
  • r/s: 每秒完成的读 I/O 设备次数。即 rio/s
  • w/s: 每秒完成的写 I/O 设备次数。即 wio/s
  • rsec/s: 每秒读扇区数。即 rsect/s
  • wsec/s: 每秒写扇区数。即 wsect/s
  • rkB/s: 每秒读 K 字节数。是 rsect/s 的一半,因为每扇区大小为 512 字节
  • wkB/s: 每秒写 K 字节数。是 wsect/s 的一半
  • avgrq-sz: 平均每次设备 I/O 操作的数据大小 (扇区)
  • avgqu-sz: 平均 I/O 队列长度
  • await: 平均每次设备 I/O 操作的等待时间 (毫秒)
  • svctm: 平均每次设备 I/O 操作的服务时间 (毫秒)
  • %util: 向设备发出 I/O 请求所占用时间的百分比(设备的带宽利用率)

经验说明:

  • %util 接近 100%,说明产生的 I/O 请求太多,I/O 系统已经满负荷,该磁盘可能存在瓶颈
  • svctm 比较接近 await,说明 I/O 几乎没有等待时间
  • await 远大于 svctm,说明 I/O 队列太长,io 响应太慢,则需要进行必要优化
  • avgqu-sz 比较大,也表示有当量 io 在等待

使用

# iostat -c
Linux 3.10.0-693.el7.x86_64 (node1) 	08/19/2020 	_x86_64_	(8 CPU)

avg-cpu:  %user   %nice %system %iowait  %steal   %idle
           5.44    0.00    1.74    0.12    0.02   92.68
# iostat -d
Linux 3.10.0-693.el7.x86_64 (node1) 	08/19/2020 	_x86_64_	(8 CPU)

Device:            tps    kB_read/s    kB_wrtn/s    kB_read    kB_wrtn
sdc               0.00         0.00         0.00       5888          0
sdb               0.00         0.00         0.00       5888          0
scd0              0.00         0.00         0.00        144          0
sda               9.16        13.63       353.34  310574466 8050084426
dm-0              0.00         0.00         0.00       5364          4
# iostat -k
Linux 3.10.0-693.el7.x86_64 (node1) 	08/19/2020 	_x86_64_	(8 CPU)

avg-cpu:  %user   %nice %system %iowait  %steal   %idle
           5.44    0.00    1.74    0.12    0.02   92.68

Device:            tps    kB_read/s    kB_wrtn/s    kB_read    kB_wrtn
sdc               0.00         0.00         0.00       5888          0
sdb               0.00         0.00         0.00       5888          0
scd0              0.00         0.00         0.00        144          0
sda               9.16        13.63       353.34  310580506 8050100296
dm-0              0.00         0.00         0.00       5364          4
# iostat -m
Linux 3.10.0-693.el7.x86_64 (node1) 	08/19/2020 	_x86_64_	(8 CPU)

avg-cpu:  %user   %nice %system %iowait  %steal   %idle
           5.44    0.00    1.74    0.12    0.02   92.68

Device:            tps    MB_read/s    MB_wrtn/s    MB_read    MB_wrtn
sdc               0.00         0.00         0.00          5          0
sdb               0.00         0.00         0.00          5          0
scd0              0.00         0.00         0.00          0          0
sda               9.16         0.01         0.35     303301    7861442
dm-0              0.00         0.00         0.00          5          0
# iostat -t
Linux 3.10.0-693.el7.x86_64 (node1) 	08/19/2020 	_x86_64_	(8 CPU)

08/19/2020 11:08:00 AM
avg-cpu:  %user   %nice %system %iowait  %steal   %idle
           5.44    0.00    1.74    0.12    0.02   92.68

Device:            tps    kB_read/s    kB_wrtn/s    kB_read    kB_wrtn
sdc               0.00         0.00         0.00       5888          0
sdb               0.00         0.00         0.00       5888          0
scd0              0.00         0.00         0.00        144          0
sda               9.16        13.63       353.34  310580506 8050140517
dm-0              0.00         0.00         0.00       5364          4
# iostat -p sdb -x 1
Linux 3.10.0-693.el7.x86_64 (node1) 	10/23/2020 	_x86_64_	(8 CPU)

avg-cpu:  %user   %nice %system %iowait  %steal   %idle
           5.83    0.00    1.80    0.12    0.02   92.23

Device:         rrqm/s   wrqm/s     r/s     w/s    rkB/s    wkB/s avgrq-sz avgqu-sz   await r_await w_await  svctm  %util
sdb               0.00     0.00    0.00    0.00     0.00     0.00    51.42     0.00    1.76    1.77    0.00   1.42   0.00
iostat -x 3
iostat -xm 1

NVMe SSD 场景下 %util 的局限性

在 NVMe SSD 场景下,传统的 I/O Utilization(利用率,通常指 iostat 中的 %util)确实非常不准,甚至具有误导性。

核心原因在于: 该指标是基于时间计算的,而不是基于性能容量计算的。它是为单队列的机械硬盘(HDD)设计的,无法反映 NVMe 这种多队列、高并发设备的真实负载。

  • HDD 时代的 %util:像单窗口的售票处。窗口前只要有人就是 100% 忙,后面的人就得等。
  • NVMe 时代的 %util:像拥有 1000 个窗口的超级售票大厅。只要有一个窗口有人在办事,监控系统就报警说大厅 100% 被占用了(时间维度)。这显然是荒谬的,因为还有 999 个窗口是空的。

%util 的计算公式本身过时了

在 Linux 的 iostat 等工具中,%util 的定义是:在采样周期内,设备有至少一个 I/O 请求在处理(In-flight)的时间比例。

  • 公式: (IO_busy_time / Sampling_interval) * 100%
  • 对于 HDD/SATA SSD: 以前的硬盘是串行处理或队列深度很浅(AHCI 通常只有 32)。如果磁盘一直有 I/O 在排队,说明磁盘确实忙不过来了,100% util 基本等于磁盘饱和。
  • 对于 NVMe SSD: NVMe 协议支持高达 64K 个队列(Queues),每个队列深度可达 64K
    • 现象: 假设你每秒钟只发几个小的 I/O 请求,只要这些请求在时间轴上连接得很紧密(一个接一个,中间没空闲),%util 就会显示 100%
    • 真相: 此时 NVMe 可能只发挥了其并发能力的 0.1%,它就像一个拥有 64000 个车道的高速公路,虽然一直有一辆车在跑(时间上由占用),但剩下的 63999 个车道都是空的。

并发能力(Parallelism)被忽略

NVMe 的核心优势是并发。

  • 传统指标视角的饱和: 只要有工人在干活,就叫(Util 100%)。
  • NVMe 的真实饱和: 必须所有工人都满负荷干活,才叫

如果你的 NVMe SSD %util 是 100%,但平均队列深度(avgqu-sz)只有 1 或者 2,说明硬盘根本没有压力。只有当队列深度达到几百甚至上千(取决于具体 SSD 的性能),才真正接近物理瓶颈。

什么是正确的分析姿势?

既然 %util 不准,分析 NVMe 性能瓶颈应该看什么?请关注以下三个核心指标:

  1. 响应时间/延迟 (Latency) —— 这是金标准
  • 指标: await (总等待时间), r_await (读延迟), w_await (写延迟)。
  • 分析方法:
    • 如果不看 %util,只看 await
    • 正常的企业级 NVMe SSD,在低负载下延迟通常在 50μs - 200μs (0.05ms - 0.2ms) 之间。
    • 如果 %util 飙升到 100%,但 await 依然保持在 0.1ms - 0.5ms 级别,说明没有瓶颈,忽略 %util 即可。
    • 只有当 await 显著上升(例如超过 5ms 或 10ms),才说明 I/O 真的拥堵了。
  1. 队列深度 (Queue Depth)
  • 指标: aqu-szavgqu-sz
  • 分析方法:
    • 观察当前的排队数量。
    • 对于 NVMe,如果 avgqu-sz 长期远小于该设备的标称最大并发数(通常 NVMe 支持极高并发),则说明未饱和。
  1. 吞吐量与 IOPS (Throughput / IOPS)
  • 指标: r/s, w/s (IOPS) 和 rkB/s, wkB/s (带宽)。
  • 分析方法:
    • 直接对比厂商提供的 Spec(规格书)。
    • 例如:Spec 说支持 3GB/s 写入,现在只有 500MB/s,但 %util 100%。此时结合延迟看,如果延迟很低,说明是应用发得不够快,而不是盘不行;如果延迟很高,可能是盘的垃圾回收(GC)在作怪或寿命将尽。

建议使用的命令与关注点:

# 使用 iostat 扩展模式
iostat -x -d 1

# 重点看这几列:
# r_await / w_await : 只要这两个低(<1ms),盘就是健康的。
# aqu-sz            : 真正堆积的任务数量。
# %util             : 直接忽略。

如果需要更深度的分析(例如分析是内核层拥堵还是设备层拥堵),建议使用 eBPF 工具(如 bcc-tools 中的 biolatencybiosnoop),它们能生成延迟的直方图,比平均值更准确。

查看 NVMe SSD 的队列深度

使用 nvme-cli 工具,查看 NVMe 设备的队列数量(Number of Queues)和队列深度(Queue Depth):

先安装 nvme-cli (apt install nvme-cliyum install nvme-cli)

查看队列数量

使用 get-feature 命令读取 Feature ID 0x07 (Number of Queues)。

# 语法:nvme get-feature <设备路径> -f 7
sudo nvme get-feature /dev/nvme0 -f 7
  • 输出示例:
    get-feature:0x7 (Number of Queues), Current value:0x3f003f
    
  • 解读: 结果是十六进制的。
    • 低 16 位 (003f -> 63) 是 Submission Queues (SQ) 的数量。
    • 高 16 位 (003f -> 63) 是 Completion Queues (CQ) 的数量。
    • 注:这里显示的通常是 I/O 队列的数量,不包含 Admin 队列。

查看队列深度(Queue Depth)

通常没有直接的命令查硬件最大深度,但可以通过 id-ctrl 查看控制器支持的能力。

sudo nvme id-ctrl /dev/nvme0 -H | grep "mqes"
  • mqes (Maximum Queue Entries Supported): 硬件支持的最大队列深度(例如 65535)。

要查看当前操作系统层生效的队列深度(软件限制):

cat /sys/block/nvme0n1/queue/nr_requests
  • 通常默认是 1023 或 HW 限制的值。
本文总阅读量 次 本站总访问量 次 本站总访客数
Home Archives Categories Tags Statistics