4. 性能监控工具:使用 iostat、vmstat、sar 等工具监控 I/O 性能

4.1 核心原理:从“黑盒”到“白盒”的监控分层

当存储 I/O 出现性能瓶颈时,我们首先需要回答三个问题:系统整体是否繁忙?瓶颈在哪个设备?I/O 请求在哪个阶段排队? 性能监控工具的价值,正是将内核中的 I/O 子系统状态以可读的指标呈现出来。Linux 下最常用的三款工具——iostat、vmstat、sar——分别从设备层、系统层和历史趋势三个维度提供观测视角。

理解这些工具的输出,需要先掌握 I/O 路径上的关键队列模型。一次读请求从应用程序发起,经过页缓存(Page Cache)、块设备层(Block Layer)的调度队列,最终到达磁盘控制器。每个环节都可能成为瓶颈:vmstat 的 b 列反映进程因等待 I/O 而阻塞的数量;iostat 的 %util 反映设备处理请求的繁忙程度;sar 则能回溯历史负载,帮助判断瓶颈是瞬时尖峰还是持续累积。

I/O 监控工具观测视角分层 应用程序 发起 read/write 系统调用 页缓存 (Page Cache) 缓存命中则无需下探 块设备层 + I/O 调度 合并/排序/队列等待 物理磁盘 / SSD / 网络存储 vmstat 观测范围 r: 运行队列 | b: 不可中断睡眠(IO等待) si/so: 交换分区换入换出 wa: CPU 等待 I/O 时间占比 iostat 观测范围 tps: 每秒传输次数 rkB/s, wkB/s: 读写吞吐量 await, %util: 等待时间与利用率 sar 观测范围 -d: 设备级历史负载 -b: 全局 I/O 统计 -q: 系统负载队列 -r: 内存与交换分区 -n: 网络统计 支持按时间间隔采样 可回溯历史数据 适合事后分析

上图展示了三款工具在 I/O 路径上的观测位置。实际定位时,建议先 vmstat 看整体,再 iostat 看设备,最后用 sar 回溯历史,形成完整的证据链。

4.2 方法流程:三工具协同定位 I/O 瓶颈

4.2.1 第一步:用 vmstat 快速判断系统是否“卡在 I/O”

vmstat 提供的是系统级视图。执行以下命令,每 2 秒采样一次,共采样 5 次:

vmstat 2 5
procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu-----
 r  b   swpd   free   buff  cache   si   so    bi    bo   in   cs us sy id wa st
 2  1      0 8123456  12345 4567890    0    0    12    34  567  890  5  3 88  4  0
 3  2      0 8123000  12345 4567890    0    0  4567  8901 2345 6789 12 15 45 28  0
 4  3      0 8118000  12345 4567890    0    0  8901 12345 3456 9012 10 20 30 40  0

关键列解读:

  • b(阻塞进程数):持续大于 2 且伴随 wa 升高,说明进程在等待 I/O 完成。
  • bi/bo(块设备每秒接收/发送的块数):bi 高表示读压力大,bo 高表示写压力大。单位是块(1 块 = 512 字节 / 1024 字节,取决于系统)。
  • wa(CPU 等待 I/O 时间百分比):持续超过 30% 时,I/O 已成为主要瓶颈。
  • si/so(交换分区换入换出):如果持续非零,说明内存不足导致频繁换页,I/O 压力被进一步放大。
判断要点:如果 b 列接近 0 且 wa 很低,但应用依然缓慢,则瓶颈可能在 CPU 或锁竞争,而非 I/O。此时应转向 top 或 pidstat 进一步排查。

4.2.2 第二步:用 iostat 定位具体设备与延迟构成

确认系统存在 I/O 瓶颈后,使用 iostat -x 查看每个设备的详细指标:

iostat -x 2 3
Device:  rrqm/s wrqm/s r/s   w/s   rkB/s   wkB/s avgrq-sz avgqu-sz await r_await w_await svctm %util
sda        0.00   12.00 0.00 145.00  0.00  4567.00    63.00     0.80    5.50    0.00    5.50  0.50 7.25
sdb        0.00   0.00  0.00  0.00   0.00   0.00      0.00     0.00    0.00    0.00    0.00  0.00 0.00
dm-0       0.00   0.00  0.00 145.00  0.00  4567.00    63.00     0.80    5.50    0.00    5.50  0.50 7.25

核心指标含义:

  • r/s, w/s:每秒读写请求数(IOPS)。
  • rkB/s, wkB/s:每秒读写吞吐量。
  • await:I/O 请求从进入队列到完成处理的平均等待时间(毫秒)。这是最直观的延迟指标。
  • r_await / w_await:区分读和写的平均等待时间。若读等待远高于写,可能是读缓存不足或磁盘寻道开销大。
  • svctm:设备实际处理请求的平均时间(不含排队)。注意:在 NVMe 或 SSD 上该值可能失真,参考意义有限。
  • %util:设备繁忙百分比。接近 100% 表示设备已饱和,但要注意 SSD 并行处理能力较强,%util 高不一定意味着延迟不可接受。
常见误区:不要单独看 %util 就下结论。例如,一个 RAID 阵列由 8 块盘组成,单块盘 %util 为 30%,但整体阵列可能已接近吞吐上限。应结合 await 和 avgqu-sz(平均队列长度)综合判断。若 await 远大于 svctm,说明排队时间过长,设备处理能力不足。

4.2.3 第三步:用 sar 回溯历史与捕捉瞬时尖峰

sar 的优势在于可以记录历史数据,适合事后分析。首先确认系统已开启 sysstat 服务,然后使用:

# 查看今天每 10 分钟的设备 I/O 统计
sar -d -f /var/log/sysstat/sa$(date +%d) | head -30

# 实时查看每 2 秒的全局 I/O 情况
sar -b 2 5

# 查看内存与交换分区
sar -r 2 5

sar -d 输出示例:

12:00:01 AM       DEV   tps  rd_sec/s  wr_sec/s  avgrq-sz  avgqu-sz  await  svctm  %util
12:10:01 AM       sda  12.5    0.00    512.00     41.00     0.01    0.80   0.40   0.50
12:20:01 AM       sda 145.0    0.00  45670.00     63.00     0.80    5.50   0.50   7.25
12:30:01 AM       sda  89.3    0.00  23456.00     52.00     0.45    3.20   0.45   4.00

通过对比不同时间点的数据,可以判断 I/O 负载是持续高位还是周期性波动,从而关联到定时任务、业务高峰等外部因素。

4.3 案例实战:定位数据库写入延迟问题

某在线交易系统反馈“订单提交变慢”,DBA 怀疑是存储问题。我们按以下流程排查:

  1. vmstat 快速检查:发现 b 列持续为 3-4,wa 达到 35%,确认存在 I/O 等待。
  2. iostat -x 定位设备:看到 sdb(数据库数据盘)的 w/s 高达 800,w_await 为 45ms,而 svctm 仅 2ms。说明大量请求在排队,磁盘处理不过来。
  3. sar -d 回溯:查看过去 2 小时的数据,发现从 14:00 开始 wr_sec/s 从 2000KB/s 飙升到 50MB/s,与业务方确认是促销活动导致写入量激增。
  4. 进一步分析:使用 iostat -x -k 1 观察 avgqu-sz(平均队列长度)持续超过 10,确认磁盘队列深度过高。

最终结论:磁盘写入吞吐达到上限,且 I/O 调度器合并效率不足。优化措施包括:将数据库日志盘与数据盘分离、调整 I/O 调度器为 none(NVMe 场景)、增加应用层批量写入。

4.4 误区与复盘:监控工具使用中的常见陷阱

误区 表现 正确做法
只看 %util 判断磁盘饱和 %util 100% 但延迟很低(SSD 场景) 结合 await 和 avgqu-sz,SSD 应关注延迟而非利用率
忽略页缓存命中率 iostat 显示高读吞吐,但实际是缓存未命中 先用 free 查看 cache 大小,或用 sar -B 查看页缓存命中率
采样间隔过短或过长 间隔 1 秒可能捕捉到瞬时尖峰造成误判;间隔 10 分钟可能遗漏关键波动 先用 2-5 秒间隔观察 1 分钟,再根据业务周期调整
未区分读写延迟 await 高但不知道是读还是写导致 查看 r_await 和 w_await,分别优化
忽略设备映射关系 看到 dm-0 高负载,但不知道对应哪块物理盘 使用 lsblk 或 dmsetup ls 确认映射关系
复盘要点:本次案例中,最初只关注了 %util,误以为磁盘已满负荷。后来通过 w_await 与 svctm 的差值发现是排队延迟,而非设备处理能力不足。进一步用 sar 回溯才找到写入量突增的根因。监控工具不是孤立使用的,vmstat 判断方向,iostat 定位设备,sar 还原时间线,三者配合才能形成完整证据链。此外,所有工具都只能反映内核视角的 I/O 状态,应用层的日志、慢查询等同样重要,需要交叉验证。

最后,建议在日常运维中养成定期采集 sar 数据的习惯(默认 sysstat 已开启),并设置阈值告警:当 await 超过 20ms(机械盘)或 5ms(SSD)时触发通知。这样在故障发生时,你已经有历史基线可供对比,能更快定位是“突然变慢”还是“持续劣化”。