在 Linux 服务器上排查性能问题时,磁盘 I/O 是一个很常见的方向。比如系统响应变慢、数据库查询变慢、日志写入延迟、程序偶尔卡住,或者 CPU 看起来不高但业务处理速度明显下降,这些情况都可能和磁盘 I/O 有关。
iostat 是一个非常常用的 Linux 性能分析命令,可以用来查看 CPU 使用情况和磁盘设备的读写情况。它适合快速判断磁盘是否繁忙、读写请求是否堆积、I/O 延迟是否过高,以及当前负载是偏读还是偏写。
我平时比较常用的命令是:
iostat 1 -d -x -p sda这条命令的作用是每 1 秒输出一次 sda 这块磁盘及其分区的详细 I/O 统计信息。
一、命令参数说明 #
这条命令可以拆开看:
iostat 1 -d -x -p sda其中:
1表示每隔 1 秒刷新一次输出。如果不指定次数,它会持续输出。
-d表示只显示设备使用情况,不显示 CPU 统计信息。
-x表示显示扩展统计信息。磁盘排查时一般都会加上这个参数,因为普通输出里的信息太少,不够判断 I/O 延迟和队列情况。
-p sda表示显示 sda 这块磁盘以及它下面的分区信息。比如可能会看到 sda、sda1、sda2 等。
如果想看所有磁盘和分区,可以使用:
iostat -d -x -p ALL 1如果是 NVMe 硬盘,设备名通常不是 sda,而是类似:
nvme0n1这时可以改成:
iostat 1 -d -x -p nvme0n1二、先注意第一屏输出 #
使用 iostat 时有一个细节需要注意:第一屏输出通常是系统启动以来的平均值,并不一定代表当前状态。官方手册也说明,第一份报告默认统计的是系统启动以来的数据,后续报告才是两次输出间隔内的数据。([Man7][1])
所以排查实时问题时,不要只看第一屏。一般可以让它连续跑几秒,多观察后面的数据。
例如:
iostat -d -x -p sda 1 10这个命令表示每 1 秒输出一次,总共输出 10 次。
如果想跳过第一屏启动以来的统计,可以使用:
iostat -y -d -x -p sda 1其中 -y 的作用就是省略第一份自系统启动以来的报告。
三、常见返回字段解释 #
不同版本的 sysstat 输出字段可能略有差异,但常见字段大致如下。
| 参数 | 含义 |
|---|---|
| Device | 设备名,例如 sda、sda1、nvme0n1 |
| r/s | 每秒完成的读请求数,已经包含合并后的结果 |
| w/s | 每秒完成的写请求数,已经包含合并后的结果 |
| rkB/s | 每秒读取的数据量,单位通常是 kB |
| wkB/s | 每秒写入的数据量,单位通常是 kB |
| rrqm/s | 每秒合并的读请求数量 |
| wrqm/s | 每秒合并的写请求数量 |
| %rrqm | 读请求在发送到设备前被合并的百分比 |
| %wrqm | 写请求在发送到设备前被合并的百分比 |
| r_await | 平均每次读请求耗时,单位毫秒,包括排队时间和服务时间 |
| w_await | 平均每次写请求耗时,单位毫秒,包括排队时间和服务时间 |
| aqu-sz | 平均 I/O 队列长度 |
| rareq-sz | 平均每个读请求大小,单位通常是 kB |
| wareq-sz | 平均每个写请求大小,单位通常是 kB |
| await | 所有 I/O 请求的平均等待时间,包含读写请求 |
| %util | 设备有 I/O 请求的时间占比,可以理解为设备繁忙程度 |
其中 await、r_await、w_await 都是毫秒级指标,并且包含请求排队时间和实际处理时间;aqu-sz 是平均队列长度;%util 表示有 I/O 请求发给设备的时间占比。官方手册也提醒,对于传统串行处理请求的设备,%util 接近 100% 往往意味着设备接近饱和;但对于 RAID、现代 SSD 等可并行处理请求的设备,不能只靠这个数字判断性能上限。([Man7][1])
四、几个最关键的指标 #
虽然 iostat -x 输出字段很多,但真正排查问题时,不需要每个字段都盯着看。一般先看下面几个。
1. %util:磁盘忙不忙 #
%util 可以理解为设备处理 I/O 的繁忙程度。
如果 %util 长时间接近 100%,说明这块磁盘一直有 I/O 请求在处理。对于机械硬盘或者传统块设备,这通常意味着磁盘压力比较大。
但对于 SSD、NVMe、RAID 阵列来说,%util 接近 100% 不一定代表性能已经完全到顶。因为这类设备可以并行处理多个请求,不能简单用机械硬盘的思路判断。
所以 %util 要结合 await 和 aqu-sz 一起看。
2. await / r_await / w_await:请求慢不慢 #
await 表示 I/O 请求从提交到完成的平均时间,包含排队和实际执行时间。
如果 await 很高,说明应用提交的 I/O 请求等了比较久。
如果是:
r_await 高说明读请求延迟高,可能影响数据库查询、文件读取、程序加载等。
如果是:
w_await 高说明写请求延迟高,可能影响日志写入、数据库事务、文件保存等。
排查时要注意看是读慢还是写慢,不要只看一个总的 await。
3. aqu-sz:请求有没有排队 #
aqu-sz 表示平均 I/O 队列长度。这个值越高,说明等待处理的请求越多。
如果 %util 高、await 高、aqu-sz 也高,通常说明磁盘压力已经比较明显,请求开始排队。
如果 %util 高但 await 不高,说明磁盘很忙,但请求处理速度还能跟上。
如果 await 高但 %util 不高,就要进一步排查是不是底层存储、虚拟化环境、网络盘、阵列、文件系统或其他原因导致延迟异常。
4. r/s、w/s、rkB/s、wkB/s:读写量有多大 #
r/s 和 w/s 是每秒读写请求数量。
rkB/s 和 wkB/s 是每秒读写数据量。
这两组指标要一起看。
如果 r/s、w/s 很高,但 rkB/s、wkB/s 不高,可能是大量小 I/O。
如果 r/s、w/s 不高,但 rkB/s、wkB/s 很高,可能是少量大块连续读写。
大量小 I/O 对机械硬盘影响很明显,对数据库、日志、缓存类业务也很常见;大块连续 I/O 则更多出现在备份、拷贝、压缩、视频处理、批量导入导出等场景。
五、如何快速判断磁盘是否成为瓶颈 #
可以按下面思路看:
第一,看 %util 是否长期很高。
如果 %util 长时间接近 100%,说明设备一直处于忙碌状态。
第二,看 await 是否明显升高。
如果 await 也高,说明请求不只是多,而且处理慢,应用层很可能会感觉到卡顿。
第三,看 aqu-sz 是否增加。
如果队列长度越来越高,说明请求堆积,磁盘处理速度跟不上业务提交速度。
第四,看是读压力还是写压力。
通过 r/s、rkB/s、r_await 判断读压力。
通过 w/s、wkB/s、w_await 判断写压力。
第五,结合业务场景判断。
例如:
- 数据库查询慢,重点看读延迟
r_await - 日志写入慢,重点看写延迟
w_await - 文件复制慢,重点看吞吐量
rkB/s、wkB/s - 系统整体卡顿,重点看
%util、await、aqu-sz - 虚拟机磁盘慢,还要考虑宿主机和底层存储
六、一个简单的观察示例 #
假设看到类似情况:
Device r/s w/s rkB/s wkB/s r_await w_await aqu-sz %util
sda 5.00 450.00 120.00 9000.00 2.00 85.00 8.50 98.00这时可以大致判断:
w/s很高,说明写请求很多wkB/s明显高于rkB/s,说明主要是写入压力w_await达到 85ms,写请求延迟较高aqu-sz为 8.50,说明有请求排队%util为 98%,设备非常忙
这种情况下,磁盘写入很可能已经成为瓶颈。接下来就应该继续查是谁在写磁盘。
可以配合使用:
iotop或者:
pidstat -d 1查看具体进程的磁盘读写情况。
七、常用命令整理 #
查看某块磁盘的详细 I/O:
iostat -d -x -p sda 1查看所有磁盘和分区:
iostat -d -x -p ALL 1只看设备,不看 CPU:
iostat -d 1显示扩展信息:
iostat -x 1跳过第一屏启动以来的平均值:
iostat -y -d -x -p sda 1连续输出 10 次:
iostat -d -x -p sda 1 10查看 NVMe 磁盘:
iostat -d -x -p nvme0n1 1八、关于 svctm 字段 #
有些旧版本 iostat 输出中会看到 svctm 字段,表示平均每次设备 I/O 操作的服务时间。
不过在较新的 sysstat 输出里,这个字段已经不一定出现。实际排查时,也不建议过度依赖 svctm。现在更常用的判断方式是看:
await
r_await
w_await
aqu-sz
%util这些指标组合起来,比单独看 svctm 更有参考价值。
九、总结 #
iostat 是 Linux 下排查磁盘 I/O 问题非常实用的命令。常用命令可以记成:
iostat -y -d -x -p sda 1其中:
-d表示只看磁盘设备-x表示显示扩展统计信息-p sda表示查看sda及其分区1表示每秒刷新一次-y表示跳过第一屏启动以来的平均值
实际排查时,重点关注:
%util
await
r_await
w_await
aqu-sz
r/s
w/s
rkB/s
wkB/s如果 %util 长时间很高,同时 await 和 aqu-sz 也升高,通常说明磁盘 I/O 压力比较明显。接下来可以结合 iotop、pidstat -d、应用日志和业务访问情况,继续定位到底是哪个进程或业务造成了磁盘压力。