登录
推荐 文章 Go 技术 课程 下载 专题 AI
首页 >  文章 >  linux

iostat 区分设备吞吐与等待时间的读取方法

来源:17golang原创

时间:2026-10-03 23:57:34 272浏览 收藏

“磁盘吞吐很高,是不是说明磁盘已经很慢?”这是看 iostat 时最常见的误区。答案是:不能只看吞吐,也不能只看等待。吞吐回答设备在单位时间搬运了多少数据,等待回答一个请求从进入队列到完成平均花了多久;两者是相关但独立的观察轴。

最实用的读法是:先用 rkB/s、wkB/s 和请求大小确认工作量,再用 r_await、w_await、await 与 aqu-sz 判断延迟和排队,最后才把 %util 当成补充证据。iostat 的字段定义可直接对照官方手册:https://man7.org/linux/man-pages/man1/iostat.1.html。

先给结论:高吞吐、低等待通常表示设备在高效工作;低吞吐、高等待更值得警惕;高吞吐、高等待说明繁忙并可能排队;低吞吐、低等待多半只是轻载。任何一种结论都要结合连续样本和设备基线,而不是用一个固定阈值判断所有磁盘。

一、先把吞吐和等待拆成两条轴

扩展报告中的字段可以分成三组。第一组是请求频率 r/s、w/s,回答每秒完成多少次读写;第二组是吞吐 rkB/s、wkB/s,回答每秒传输多少 KiB;第三组是等待和队列,主要看 r_await、w_await、await 与 aqu-sz。

rareq-sz 与 wareq-sz 是连接前两组的重要字段。相同的 IOPS 可能由大量小请求构成,也可能由少量大请求构成;如果跳过请求大小,只比较 r/s 或 w/s,很容易把完全不同的负载形态混在一起。

iostat 请求频率、吞吐与等待字段的双轴静态关系图
图1:iostat 的请求频率、吞吐、请求大小与等待队列属于不同观察维度;这是原创关系图,不是终端截图。

二、为什么第一次输出经常误导判断

不带间隔参数时,iostat 的第一份报告通常是从系统启动以来的累计统计。即使指定了采样间隔,第一份也可能仍然是累计视角。它适合看长期平均,却不适合回答“刚才这次发布为什么慢”。使用 -y 可以跳过第一份累计报告,把注意力放到后续区间样本。

# -x 输出设备扩展字段,包括吞吐、await、队列和利用率
# -y 跳过从开机到现在的首份累计报告
# 每 1 秒采样一次,共输出 10 份区间报告
iostat -x -y 1 10

不要拿一次采样中的单个峰值直接定性。更稳妥的方式是同时记录故障发生前、发生中和恢复后的连续样本,并与同一设备在正常业务时段的基线比较。这里没有适用于所有 HDD、SSD、NVMe、云盘和阵列的统一 await 阈值。

三、先读吞吐,再读等待

1. 吞吐字段回答“设备搬了多少”

字段含义读取重点
r/s、w/s每秒完成的读、写请求数观察 IOPS 形态,不能替代字节吞吐
rkB/s、wkB/s每秒读取、写入的 KiB表示数据搬运量,需与设备规格或历史基线比较
rareq-sz、wareq-sz平均读、写请求大小区分小块随机负载与大块顺序负载

例如,r/s 很高而 rkB/s 并不突出,往往表示请求较小;r/s 不高但 rkB/s 很高,则可能是较大的读请求。这里描述的是负载形态,而不是性能好坏。

2. 等待字段回答“请求等了多久”

字段含义读取重点
r_await读请求平均完成时间,包含排队和服务时间读慢而写正常时比总 await 更有定位价值
w_await写请求平均完成时间,包含排队和服务时间写回、日志或检查点场景应单独观察
await所有 I/O 请求的平均完成时间便于总览,但可能掩盖读写差异
aqu-sz平均队列长度,旧版本常显示为 avgqu-sz与 await 一起上升时,排队解释更有说服力

官方定义中的 await 包含请求在队列中的时间和被设备服务的时间。因此它不是纯粹的“介质响应时间”。当设备映射、限速层、阵列控制器或云盘后端加入额外等待时,iostat 在当前层看到的是总完成时间。

四、把两条轴组合成四种结论

iostat 吞吐与等待四象限静态判断图
图2:吞吐与等待组合后形成四类现象,aqu-sz、请求大小和 %util 用于补充解释;这是原创分析图。

高吞吐、低等待:设备正在高效搬运数据

这种组合通常不应因为“吞吐很高”就被判定为瓶颈。设备可能只是正常承接大块顺序读写。继续检查业务响应是否正常、请求大小是否符合预期即可。如果业务延迟稳定,没有必要为了压低吞吐而干预。

低吞吐、高等待:优先寻找阻塞与异常延迟

数据搬运量不高但请求仍然等待很久,常见解释包括下层设备抖动、云盘限速、故障重试、设备映射层阻塞,或少量同步 I/O 被拉长。此时应观察 aqu-sz 是否同步增加,并继续向 LVM、device-mapper、RAID 或云盘监控下钻。

高吞吐、高等待:设备繁忙且可能出现排队

高工作量与高等待同时存在,说明设备正在处理大量数据,且请求完成时间已经上升。若 aqu-sz 同时增长,排队解释更强。下一步应确认业务延迟是否越过 SLO,以及是大请求吞吐占满带宽,还是高 IOPS 让并发队列变深。

低吞吐、低等待:多半是空闲或轻载

这通常是健康的轻载状态。如果应用仍然报告“磁盘慢”,就要警惕观察对象不对:应用可能访问了另一个设备,数据命中了页缓存,或者延迟发生在文件系统、网络存储、锁竞争和应用同步逻辑中。

五、%util 为什么不能单独作结论

%util 表示采样区间内,有 I/O 请求提交到设备的时间占比。对一次只服务一个请求的串行设备,它接近 100% 时往往意味着饱和;但现代 SSD、NVMe、RAID 和多路径设备可以并行服务多个请求,%util 接近 100% 并不自动等于已经达到真实性能上限。

同理,CPU 报告中的 %iowait 也不能证明某块磁盘就是瓶颈。它描述 CPU 在有未完成磁盘 I/O 时处于空闲的时间比例,仍需与具体设备的吞吐、await、队列和业务延迟对应起来。

六、实战读取顺序:从设备映射到连续样本

# 先确认挂载点最终对应哪个块设备以及中间映射层
lsblk -o NAME,TYPE,SIZE,FSTYPE,MOUNTPOINTS

# 再采集扩展字段;跳过首份累计报告并保留连续区间
iostat -x -y 1 10

拿到输出后,按下面的顺序读,不需要一上来盯住所有列:

  1. 先定位目标设备,避免把逻辑卷、物理盘或无关盘混在一起。
  2. 看 rkB/s、wkB/s,确认当前读写方向和数据量。
  3. 看 r/s、w/s 与平均请求大小,识别请求形态。
  4. 看 r_await、w_await,避免总 await 掩盖单一方向。
  5. 看 aqu-sz 是否随 await 增长,判断是否存在持续排队。
  6. 最后参考 %util,再与应用延迟、设备规格和历史基线交叉验证。

七、三个容易越界的场景

页缓存让“应用读很多”不等于“设备读很多”

应用读取的数据如果命中 Linux 页缓存,块设备层不一定出现对应的 rkB/s。因此“业务读取量大、iostat 吞吐低”并不矛盾。需要结合缓存命中、内存回收和应用侧指标判断。

LVM、RAID 与云盘要沿映射层读取

逻辑卷、md 阵列、device-mapper 设备和底层物理盘可能呈现不同的吞吐与等待。只看其中一层,可能漏掉条带分布、镜像写放大、限速或下层单盘异常。先用 lsblk 明确拓扑,再选择需要对照的设备行。

NVMe 的并行性削弱单一 util 指标

NVMe 能并行处理多个队列和请求。此时更应该看延迟是否偏离基线、队列是否持续加深、吞吐是否接近设备规格,以及业务 SLO 是否受到影响,而不是把 %util=100% 直接翻译成“磁盘满载”。

常见问题

await 多高才算异常?

没有跨设备通用的固定值。HDD、SATA SSD、NVMe、本地盘和云盘的正常区间不同,同一设备在同步日志与批量吞吐场景中的目标也不同。优先与该设备的正常基线、业务延迟目标和厂商规格比较。

aqu-sz 高就一定是队列堵塞吗?

不一定。支持并行的设备可以在较深队列下保持低 await 和稳定吞吐。只有当队列持续加深、await 同步上升并且业务延迟恶化时,才更像是有害排队。

为什么 await 很高,但 %util 不高?

可能是少量请求被下层限速、重试或异常延迟拉长,也可能当前观察层与真正慢的设备层不一致。此时低吞吐、高等待本身就是重要信号,应继续检查映射层、云盘额度和错误日志。

只看 r/s、w/s 可以判断负载吗?

不够。请求次数必须与 rkB/s、wkB/s 和平均请求大小一起看。大量小请求与少量大请求可能产生相似吞吐,却对队列和延迟造成不同影响。

归根结底,iostat 不是“找出一个红色数字”的工具,而是把设备工作量与请求等待拆开观察。先确认样本窗口,再读吞吐和请求形态,然后读等待与队列,最后把利用率放回设备并行能力和业务 SLO 中解释,才能避免把正常高负载误判成故障,也能更快识别真正的低吞吐高等待问题。

声明:本文转载于:17golang原创 如有侵犯,请联系study_golang@163.com删除
相关阅读
更多>
最新阅读
更多>
课程推荐
更多>