1. 为什么排查磁盘问题我总是第一个打开 iostat干运维和后台开发这些年,只要线上出现“服务卡顿”“接口超时”“数据库突然变慢”,我下意识就会敲一条命令看看磁盘到底在干嘛。这条命令就是iostat。它不是万能的,但绝对是最先该看的那个——因为磁盘 I/O 性能问题往往藏得很深,CPU 高了你一眼就能看到,内存满了 top 也能立刻暴露,唯独磁盘这块,你不主动去测去查,它可能默默拖垮整个业务,而你还在傻乎乎地调应用代码。iostat是 Linux sysstat 软件包里的一个性能分析工具,专门用来监控系统的输入输出设备负载情况,说人话就是:它告诉你磁盘当前有多忙、读写速度是多少、I/O 请求排了多长的队、每个请求等了多久才被处理完。这些信息对定位“存储瓶颈”至关重要。这篇内容我打算从一个实际使用者的角度,把 iostat 的指标、参数、使用场景、常见坑全部梳理一遍。不管你是刚入行的运维新人,还是写后端服务的开发,这篇内容都能帮你少走弯路。我尽量不说废话,直接用我这么多年踩过的坑和验证过的方法来讲。2. iostat 到底能干什么,不能干什么2.1 能立刻回答的问题拿过一台出问题的机器,iostat 能帮我在十秒内回答这几件事:磁盘的读写吞吐量(每秒传输多少 KB/MB)是否已经逼近硬件上限。I/O 请求的平均响应时间(await)是否高得离谱,比如正常零点几毫秒,结果变成几十毫秒。磁盘设备的利用率(%util)是否长期处于 100% 附近,也就是“打满了”。多个磁盘或分区之间负载是否均衡,是不是有人把数据全写到了同一块盘上。这些信息拿到手,基本就能判断“是磁盘本身不行,还是应用程序把磁盘搞垮了”。2.2 不能回答的问题但 iostat 也有明显的盲区。它只能告诉你“磁盘很忙”,但没法告诉你“到底是谁在写”。这时候需要配合pidstat或iotop去看具体进程。另外,它提供的是聚合后的平均值,突发性的瞬时抖动容易被“平均”掉。比如某块盘 1 秒内的峰值延迟是 100ms,但 iostat 默认 2 秒间隔取均值,出来后可能是 5ms,掩盖了真相。所以,我对 iostat 的定位很明确:它是一个“第一现场勘察工具”,先把问题定性,再结合其他工具做定量和定位。3. 核心指标逐个拆解:这些数字到底代表什么iostat 输出内容分两部分:CPU 使用情况和设备使用情况。CPU 部分大家比较熟,重点看设备部分的几个字段。我第一次用的时候被svctm这个名字误导了很久,后面详细说。3.1 设备报告核心字段以iostat -x 1 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 vda 0.00 0.00 0.00 1.00 0.00 4.00 8.00 0.00 0.50 0.00 0.50 0.50 0.05逐字段拆解:r/s 和 w/s:每秒完成的读请求数和写请求数。注意这里的单位是“次数”,不是数据量。IOPS(每秒读写次数)主要就是看这两个值。rkB/s 和 wkB/s:每秒读写的数据量,单位是 KB。吞吐量的核心指标。avgrq-sz:平均每次 I/O 请求的数据大小。如果这个值很小(比如 8KB),说明应用在做大量的小块随机读写;如果很大(比如 1MB),说明在做顺序大块读写。这个字段能帮你判断应用访问模式。avgqu-sz:平均 I/O 队列长度。队列越长,说明请求在排队等待,磁盘处理不过来。await:平均每次 I/O 请求从发出到完成的总耗时,包括在队列里等待的时间。这个值是判断“用户感知延迟”的关键指标。再细分还有r_await和w_await,分别看读和写的延迟。svctm:平均每次 I/O 请求在硬件层面实际处理的时间。这个字段在新版 Linux 里已经基本没有参考意义,因为很多存储设备(比如 SSD、云盘、分布式存储)的处理时间内核根本无法准确统计。注意:svctm在很多资料里还被拿来分析,但内核维护者早就说过,这个值在现代设备上不可靠。我一般直接忽略它,重点看await和%util。%util:设备繁忙程度百分比。可以粗略理解为“设备有百分之多少的时间在干活”。很多人以为 100% 就是满负荷,其实不完全准确。这个后面专门讲。3.2 CPU 部分的 %iowait 怎么看iostat 输出的第一段是 CPU 状态,其中%iowait表示 CPU 等待 I/O 完成的时间占比。这个值如果很高(比如超过 30%),说明 CPU 大多数时间在干等磁盘返回数据,应用层会感受到明显的卡顿。但要注意,%iowait高不代表磁盘就是坏的。它只说明 CPU 在等待 I/O,磁盘可能正常工作,只是负载重。也可能是因为进程数太少,CPU 没别的活干只好等着。我见过不少情况是:%iowait高达 40%,但实际上磁盘根本没有满负荷,纯粹是业务进程在同步等待锁或者网络资源,误把等待时间算进了 I/O。4. 常用参数组合与场景化使用iostat 的参数不多,但组合起来有不同的用途。我把我平时最常用的几套组合整理成了一个速查表,方便大家直接抄作业。4.1 参数速查表命令组合用途说明适用场景iostat -x 1每秒刷新一次,显示详细扩展指标实时观察磁盘负载变化iostat -x 1 5每秒一次,共采集 5 次抓取一段时间内的平均表现iostat -d -k 1只看设备报告,以 KB 为单位快速确认哪块盘吞吐异常iostat -p /dev/vda 1只看指定分区或磁盘多盘机器定位问题盘iostat -m 1以 MB 为单位显示吞吐大吞吐场景下避免数字太长iostat -x -t 1附带时间戳输出需要配合日志定位时间线我的习惯是:先跑iostat -x 1 3,拿到 3 组数据,观察%util和await的走势;如果发现某块盘异常,再跑iostat -p /dev/sdb -x 1单盘盯一会儿。注意采样次数不要太多,3 次足够了,因为 iostat 只输出从启动以来的平均值和间隔内的增量值,次数再多也是重复。4.2 动态刷新间隔的讲究很多人用iostat 1就一直挂在那里刷屏,其实没必要。默认情况下 iostat 第一行输出的是“系统启动至今的平均值”,后面才是每个间隔内的数据。如果你只看第一行去判断问题,会被启动以来长时间的平均值严重误导。举个例子,一台机器跑了 30 天,平均%util是 20%,但最近 1 分钟磁盘已经打满 100%。你第一眼看到的是 20%,就会误判“磁盘还好啊”。所以正确姿势是:至少看第二行之后的采样数据,或者用iostat -x 1 3这种明确采样次数的方式,把第一行平均值忽略掉。5. 实操案例:一次典型的“磁盘打满”排查我之前处理过一个问题,某公司的订单服务突然延迟飙高,数据库的慢查询日志里全是简单查询超时。我上去之后,没有先看慢查询,而是直接跑iostat -x 1 5。5.1 初步定位输出的关键信息大致是:Device: rrqm/s wrqm/s r/s w/s rkB/s wkB/s avgqu-sz await r_await w_await %util nvme0n1 0.00 2048.00 0.00 2048.00 0.00 8192.00 12.00 11.50 0.00 11.50 100.00分析一下:w/s高达 2048,也就是每秒 2048 次写请求,这已经是一个非常高的 IOPS 值。avgqu-sz是 12,意味着平均有 12 个请求在排队等待处理。await是 11.5ms,对于 NVMe 盘来说偏高太多。正常 NVMe 盘的延迟应该在零点几毫秒到几毫秒之间。%util是 100%,磁盘已经满负荷。到这基本可以断定:存储层扛不住了,但“谁在写”还不知道。5.2 定位写源头接着用pidstat -d 1 5查看每个进程的 I/O 情况,很快就发现是一个日志收集进程在疯狂写文件,并且日志轮转配置失效,导致单个日志文件无限增长。顺序写变成了大量的小块追加写,再加上磁盘本身是共享存储,其他服务也受影响,最终整个存储池的队列被拉满。5.3 解决的思路直接把日志进程的写入方式改成异步批量写,同时修复日志轮转,把单文件大小限制住。改完再跑iostat -x 1 5,w/s从 2048 降到了 200 左右,await回落到 1ms 以内。这里我想强调一点:排查 I/O 性能问题,不能只看 iostat,它是第一棒,但绝不是最后一棒。拿到“磁盘满”这个结论之后,一定要配合进程级工具找到真正的元凶,否则你可能会做出错误的扩容决策——比如以为磁盘不够用,直接加盘,结果问题根本不在容量上。6. 三个最常见的误判:%util、await 和 io 瓶颈的真相6.1 %util 100% 就是磁盘饱和?不一定%util 的含义是“设备繁忙时间占总时间的百分比”,它的计算方式是基于设备是否“有未完成的请求”来判断的。问题在于:现代磁盘大多支持多队列并行处理,即使设备一直有请求在处理(%util=100%),也可能远没到硬件极限。比如 SSD 内部有多个并行通道,一块盘同时处理几十个请求都是常态,这时候 %util 一直显示 100%,但实际吞吐和延迟都表现正常。反之,有些场景 %util 不高,但延迟已经暴涨。分布式存储或者云盘就是典型——网络抖动、存储节点热点会导致请求排队,但本地设备看起来并不忙。所以我的经验是:%util 高要警惕,但不要只凭它下结论。还要结合 IOPS、吞吐量、延迟三个维度综合判断。真正衡量磁盘是否饱和,应该看“当前 IOPS/吞吐是否接近该设备的标称上限”。6.2 await 高就是磁盘慢?小心被平均数骗了await 是“从发出请求到完成”的平均时间,包含排队时间和处理时间。如果你的应用的 I/O 模式是随机小块读写,单次请求本身需要寻址,延迟天然比顺序读写高。这并不代表磁盘坏了,只是访问模式导致的。更隐蔽的一个坑是:平均值掩盖了长尾延迟。有时候磁盘 99% 的请求都在 1ms 内完成,但剩下的 1% 请求要 100ms,平均值算出来是 2ms 左右,表面看很健康,可业务却出现了偶发超时。这种情况我建议配合iostat -x里的r_await和w_await分开看,或者用延迟分布工具去抓长尾请求,只看平均值会误事。6.3 I/O 瓶颈不如 CPU 瓶颈好判断CPU 瓶颈很容易判断:某个核的%user或者%sys飙到 100%,就是 CPU 不够了。但 I/O 瓶颈牵扯到设备类型、队列深度、总线带宽、远端存储网络等多个环节,光靠一个工具讲不清楚。我在实践中总结了一套判断流程,大家可以参考:先看iostat -x,确认是读还是写,是 IOPS 高还是吞吐高。对照设备规格确认是否逼近上限。用pidstat -d或iotop定位具体进程。用strace或者应用日志确认 I/O 请求的大小和频率。结合业务高峰和监控曲线找规律。这套流程走完,I/O 问题一般都能定位到八九不离十。7. 容易被忽略的细节:采样时间、设备命名和输出格式7.1 采样间隔不是随便定的iostat 默认输出是自系统启动以来的平均值,所以如果你直接在机器上敲iostat不加参数,看到的数据参考价值有限。正确的做法是带间隔和次数,比如iostat -x 1 3。间隔的选择也有讲究:间隔太短(比如 0.1 秒)会占用额外资源,在本身就繁忙的机器上造成干扰;间隔太长(比如 60 秒)又可能把短时峰值抹平。生产环境我一般用 1 秒或 2 秒间隔,采 3 到 5 次就够看了。7.2 设备名不同,含义不同现在的服务器设备命名越来越复杂:/dev/sda一般是本地 SCSI/SATA 盘,/dev/nvme0n1是 NVMe SSD,/dev/vda是虚拟化环境下的虚拟磁盘,/dev/mapper/xxx是 LVM 逻辑卷。如果某台机器有多块盘,iostat 默认会全部列出来。我见过有人盯着/dev/sda猛看,却发现真正的数据库数据在/dev/sdb上,白忙活半天。用iostat -p参数指定设备名,或者先跑lsblk确认设备和挂载点的对应关系,再针对性监控。另外,在云环境里,一块云盘背后的实际硬件可能有多块物理盘支撑,iostat 看到的只是你这一朵“云盘视图”,不代表物理硬件状态,这一点要心里有数。7.3 第一行数据是“累计平均”这个前面提过,但还是值得单独强调:iostat 输出的第一行是自启动以来的累计平均,之后才是按间隔采样的数据。判断当前瓶颈时,请忽略第一行,直接看后续采样值。尤其是机器跑了很久、历史负载又不高的时候,第一行的平均值会把当前峰值严重稀释。8. iostat 的局限性与搭档工具没有任何工具是万能的,iostat 也不例外。它在“系统级”的 I/O 监控上很强大,但深入一步就会力不从心。这里整理一下我的常用搭档组合。8.1 进程级定位:pidstat 和 iotopiostat 告诉你系统整体 I/O 情况,但如果想知道具体哪个进程在产生 I/O,就要用pidstat -d或者iotop。前者按进程显示读写速率,适合脚本化采集;后者类似 top 的交互界面,适合人工观察。对比起来,我写脚本排查时偏好 pidstat,手动登录机器时偏好 iotop。8.2 延迟细节追踪:iostat 看不到的长尾如果需要更精确的延迟分布,iostat给不了。/proc文件系统里的io信息可以辅助,但更直接的是用blktrace、fio这类专业工具。fio可以主动压测磁盘性能,blktrace可以追踪 I/O 请求在内核里的整个旅程。不过这两个工具学习成本稍高,一般只有深挖问题时才用得着。8.3 配合监控平台长期采集日常巡检我建议写一个脚本,定期把iostat -x的采样结果落到监控平台,保留历史数据。因为很多 I/O 问题是慢慢劣化的,比如磁盘坏道逐渐增多、SSD 写入放大越来越严重,这些都是量变到质变的过程。没有历史数据,你很难说清楚“这个延迟是不是最近才变高的”。9. 一个小技巧:用 iostat 做磁盘选型和容量规划除了排障,iostat 还能帮你做一件很有价值的事——用真实业务负载来评估磁盘选型。比如你计划给新服务配存储,不确定该用高性能 SSD 还是普通 HDD,与其听厂商宣传,不如在当前机器上模拟业务负载跑一遍。方法是:先在测试环境用fio模拟业务的 I/O 模式(随机读写还是顺序读写,块大小多少,队列深度多少),再用iostat -x采集实际表现。比如业务是典型的 4KB 随机读,队列深度 32,那你就用 fio 按这个参数压测,然后对比 iostat 里的await和%util,看这台磁盘能否承受预期的 IOPS。我个人经验:不要盲目看标称 IOPS,厂商给的数字通常是最优条件下的极限值,真实环境能达到标称的 30% 到 50% 就算不错。iostat 配合 fio 的数据,比厂商宣传页可靠得多。10. 后续还能怎么扩展iostat 只是 Linux 性能分析工具箱里的一个成员。如果你发现磁盘没问题,但服务还是慢,那就要去排查网络(nicstat)、内存(vmstat)、CPU 上下文切换(pidstat -w)了。性能问题的排查思路是“先全局后局部,先系统后进程”,iostat 承担的是全局第一棒,跑好这一棒,后续方向才不会偏。我在实际使用中最深的一个体会是:工具再熟悉,也不如对业务场景的理解重要。同样的await=20ms,在 OLTP 数据库上可能是灾难,在批量分析任务里可能完全能接受。所以拿到 iostat 数据之后,一定要回到业务视角去判断“这个值对我来说到底算不算高”。
1. 为什么排查磁盘问题我总是第一个打开 iostat干运维和后台开发这些年,只要线上出现“服务卡顿”“接口超时”“数据库突然变慢”,我下意识就会敲一条命令看看磁盘到底在干嘛。这条命令就是iostat。它不是万能的,但绝对是最先该看的那个——因为磁盘 I/O 性能问题往往藏得很深,CPU 高了你一眼就能看到,内存满了 top 也能立刻暴露,唯独磁盘这块,你不主动去测去查,它可能默默拖垮整个业务,而你还在傻乎乎地调应用代码。iostat是 Linux sysstat 软件包里的一个性能分析工具,专门用来监控系统的输入输出设备负载情况,说人话就是:它告诉你磁盘当前有多忙、读写速度是多少、I/O 请求排了多长的队、每个请求等了多久才被处理完。这些信息对定位“存储瓶颈”至关重要。这篇内容我打算从一个实际使用者的角度,把 iostat 的指标、参数、使用场景、常见坑全部梳理一遍。不管你是刚入行的运维新人,还是写后端服务的开发,这篇内容都能帮你少走弯路。我尽量不说废话,直接用我这么多年踩过的坑和验证过的方法来讲。2. iostat 到底能干什么,不能干什么2.1 能立刻回答的问题拿过一台出问题的机器,iostat 能帮我在十秒内回答这几件事:磁盘的读写吞吐量(每秒传输多少 KB/MB)是否已经逼近硬件上限。I/O 请求的平均响应时间(await)是否高得离谱,比如正常零点几毫秒,结果变成几十毫秒。磁盘设备的利用率(%util)是否长期处于 100% 附近,也就是“打满了”。多个磁盘或分区之间负载是否均衡,是不是有人把数据全写到了同一块盘上。这些信息拿到手,基本就能判断“是磁盘本身不行,还是应用程序把磁盘搞垮了”。2.2 不能回答的问题但 iostat 也有明显的盲区。它只能告诉你“磁盘很忙”,但没法告诉你“到底是谁在写”。这时候需要配合pidstat或iotop去看具体进程。另外,它提供的是聚合后的平均值,突发性的瞬时抖动容易被“平均”掉。比如某块盘 1 秒内的峰值延迟是 100ms,但 iostat 默认 2 秒间隔取均值,出来后可能是 5ms,掩盖了真相。所以,我对 iostat 的定位很明确:它是一个“第一现场勘察工具”,先把问题定性,再结合其他工具做定量和定位。3. 核心指标逐个拆解:这些数字到底代表什么iostat 输出内容分两部分:CPU 使用情况和设备使用情况。CPU 部分大家比较熟,重点看设备部分的几个字段。我第一次用的时候被svctm这个名字误导了很久,后面详细说。3.1 设备报告核心字段以iostat -x 1 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 vda 0.00 0.00 0.00 1.00 0.00 4.00 8.00 0.00 0.50 0.00 0.50 0.50 0.05逐字段拆解:r/s 和 w/s:每秒完成的读请求数和写请求数。注意这里的单位是“次数”,不是数据量。IOPS(每秒读写次数)主要就是看这两个值。rkB/s 和 wkB/s:每秒读写的数据量,单位是 KB。吞吐量的核心指标。avgrq-sz:平均每次 I/O 请求的数据大小。如果这个值很小(比如 8KB),说明应用在做大量的小块随机读写;如果很大(比如 1MB),说明在做顺序大块读写。这个字段能帮你判断应用访问模式。avgqu-sz:平均 I/O 队列长度。队列越长,说明请求在排队等待,磁盘处理不过来。await:平均每次 I/O 请求从发出到完成的总耗时,包括在队列里等待的时间。这个值是判断“用户感知延迟”的关键指标。再细分还有r_await和w_await,分别看读和写的延迟。svctm:平均每次 I/O 请求在硬件层面实际处理的时间。这个字段在新版 Linux 里已经基本没有参考意义,因为很多存储设备(比如 SSD、云盘、分布式存储)的处理时间内核根本无法准确统计。注意:svctm在很多资料里还被拿来分析,但内核维护者早就说过,这个值在现代设备上不可靠。我一般直接忽略它,重点看await和%util。%util:设备繁忙程度百分比。可以粗略理解为“设备有百分之多少的时间在干活”。很多人以为 100% 就是满负荷,其实不完全准确。这个后面专门讲。3.2 CPU 部分的 %iowait 怎么看iostat 输出的第一段是 CPU 状态,其中%iowait表示 CPU 等待 I/O 完成的时间占比。这个值如果很高(比如超过 30%),说明 CPU 大多数时间在干等磁盘返回数据,应用层会感受到明显的卡顿。但要注意,%iowait高不代表磁盘就是坏的。它只说明 CPU 在等待 I/O,磁盘可能正常工作,只是负载重。也可能是因为进程数太少,CPU 没别的活干只好等着。我见过不少情况是:%iowait高达 40%,但实际上磁盘根本没有满负荷,纯粹是业务进程在同步等待锁或者网络资源,误把等待时间算进了 I/O。4. 常用参数组合与场景化使用iostat 的参数不多,但组合起来有不同的用途。我把我平时最常用的几套组合整理成了一个速查表,方便大家直接抄作业。4.1 参数速查表命令组合用途说明适用场景iostat -x 1每秒刷新一次,显示详细扩展指标实时观察磁盘负载变化iostat -x 1 5每秒一次,共采集 5 次抓取一段时间内的平均表现iostat -d -k 1只看设备报告,以 KB 为单位快速确认哪块盘吞吐异常iostat -p /dev/vda 1只看指定分区或磁盘多盘机器定位问题盘iostat -m 1以 MB 为单位显示吞吐大吞吐场景下避免数字太长iostat -x -t 1附带时间戳输出需要配合日志定位时间线我的习惯是:先跑iostat -x 1 3,拿到 3 组数据,观察%util和await的走势;如果发现某块盘异常,再跑iostat -p /dev/sdb -x 1单盘盯一会儿。注意采样次数不要太多,3 次足够了,因为 iostat 只输出从启动以来的平均值和间隔内的增量值,次数再多也是重复。4.2 动态刷新间隔的讲究很多人用iostat 1就一直挂在那里刷屏,其实没必要。默认情况下 iostat 第一行输出的是“系统启动至今的平均值”,后面才是每个间隔内的数据。如果你只看第一行去判断问题,会被启动以来长时间的平均值严重误导。举个例子,一台机器跑了 30 天,平均%util是 20%,但最近 1 分钟磁盘已经打满 100%。你第一眼看到的是 20%,就会误判“磁盘还好啊”。所以正确姿势是:至少看第二行之后的采样数据,或者用iostat -x 1 3这种明确采样次数的方式,把第一行平均值忽略掉。5. 实操案例:一次典型的“磁盘打满”排查我之前处理过一个问题,某公司的订单服务突然延迟飙高,数据库的慢查询日志里全是简单查询超时。我上去之后,没有先看慢查询,而是直接跑iostat -x 1 5。5.1 初步定位输出的关键信息大致是:Device: rrqm/s wrqm/s r/s w/s rkB/s wkB/s avgqu-sz await r_await w_await %util nvme0n1 0.00 2048.00 0.00 2048.00 0.00 8192.00 12.00 11.50 0.00 11.50 100.00分析一下:w/s高达 2048,也就是每秒 2048 次写请求,这已经是一个非常高的 IOPS 值。avgqu-sz是 12,意味着平均有 12 个请求在排队等待处理。await是 11.5ms,对于 NVMe 盘来说偏高太多。正常 NVMe 盘的延迟应该在零点几毫秒到几毫秒之间。%util是 100%,磁盘已经满负荷。到这基本可以断定:存储层扛不住了,但“谁在写”还不知道。5.2 定位写源头接着用pidstat -d 1 5查看每个进程的 I/O 情况,很快就发现是一个日志收集进程在疯狂写文件,并且日志轮转配置失效,导致单个日志文件无限增长。顺序写变成了大量的小块追加写,再加上磁盘本身是共享存储,其他服务也受影响,最终整个存储池的队列被拉满。5.3 解决的思路直接把日志进程的写入方式改成异步批量写,同时修复日志轮转,把单文件大小限制住。改完再跑iostat -x 1 5,w/s从 2048 降到了 200 左右,await回落到 1ms 以内。这里我想强调一点:排查 I/O 性能问题,不能只看 iostat,它是第一棒,但绝不是最后一棒。拿到“磁盘满”这个结论之后,一定要配合进程级工具找到真正的元凶,否则你可能会做出错误的扩容决策——比如以为磁盘不够用,直接加盘,结果问题根本不在容量上。6. 三个最常见的误判:%util、await 和 io 瓶颈的真相6.1 %util 100% 就是磁盘饱和?不一定%util 的含义是“设备繁忙时间占总时间的百分比”,它的计算方式是基于设备是否“有未完成的请求”来判断的。问题在于:现代磁盘大多支持多队列并行处理,即使设备一直有请求在处理(%util=100%),也可能远没到硬件极限。比如 SSD 内部有多个并行通道,一块盘同时处理几十个请求都是常态,这时候 %util 一直显示 100%,但实际吞吐和延迟都表现正常。反之,有些场景 %util 不高,但延迟已经暴涨。分布式存储或者云盘就是典型——网络抖动、存储节点热点会导致请求排队,但本地设备看起来并不忙。所以我的经验是:%util 高要警惕,但不要只凭它下结论。还要结合 IOPS、吞吐量、延迟三个维度综合判断。真正衡量磁盘是否饱和,应该看“当前 IOPS/吞吐是否接近该设备的标称上限”。6.2 await 高就是磁盘慢?小心被平均数骗了await 是“从发出请求到完成”的平均时间,包含排队时间和处理时间。如果你的应用的 I/O 模式是随机小块读写,单次请求本身需要寻址,延迟天然比顺序读写高。这并不代表磁盘坏了,只是访问模式导致的。更隐蔽的一个坑是:平均值掩盖了长尾延迟。有时候磁盘 99% 的请求都在 1ms 内完成,但剩下的 1% 请求要 100ms,平均值算出来是 2ms 左右,表面看很健康,可业务却出现了偶发超时。这种情况我建议配合iostat -x里的r_await和w_await分开看,或者用延迟分布工具去抓长尾请求,只看平均值会误事。6.3 I/O 瓶颈不如 CPU 瓶颈好判断CPU 瓶颈很容易判断:某个核的%user或者%sys飙到 100%,就是 CPU 不够了。但 I/O 瓶颈牵扯到设备类型、队列深度、总线带宽、远端存储网络等多个环节,光靠一个工具讲不清楚。我在实践中总结了一套判断流程,大家可以参考:先看iostat -x,确认是读还是写,是 IOPS 高还是吞吐高。对照设备规格确认是否逼近上限。用pidstat -d或iotop定位具体进程。用strace或者应用日志确认 I/O 请求的大小和频率。结合业务高峰和监控曲线找规律。这套流程走完,I/O 问题一般都能定位到八九不离十。7. 容易被忽略的细节:采样时间、设备命名和输出格式7.1 采样间隔不是随便定的iostat 默认输出是自系统启动以来的平均值,所以如果你直接在机器上敲iostat不加参数,看到的数据参考价值有限。正确的做法是带间隔和次数,比如iostat -x 1 3。间隔的选择也有讲究:间隔太短(比如 0.1 秒)会占用额外资源,在本身就繁忙的机器上造成干扰;间隔太长(比如 60 秒)又可能把短时峰值抹平。生产环境我一般用 1 秒或 2 秒间隔,采 3 到 5 次就够看了。7.2 设备名不同,含义不同现在的服务器设备命名越来越复杂:/dev/sda一般是本地 SCSI/SATA 盘,/dev/nvme0n1是 NVMe SSD,/dev/vda是虚拟化环境下的虚拟磁盘,/dev/mapper/xxx是 LVM 逻辑卷。如果某台机器有多块盘,iostat 默认会全部列出来。我见过有人盯着/dev/sda猛看,却发现真正的数据库数据在/dev/sdb上,白忙活半天。用iostat -p参数指定设备名,或者先跑lsblk确认设备和挂载点的对应关系,再针对性监控。另外,在云环境里,一块云盘背后的实际硬件可能有多块物理盘支撑,iostat 看到的只是你这一朵“云盘视图”,不代表物理硬件状态,这一点要心里有数。7.3 第一行数据是“累计平均”这个前面提过,但还是值得单独强调:iostat 输出的第一行是自启动以来的累计平均,之后才是按间隔采样的数据。判断当前瓶颈时,请忽略第一行,直接看后续采样值。尤其是机器跑了很久、历史负载又不高的时候,第一行的平均值会把当前峰值严重稀释。8. iostat 的局限性与搭档工具没有任何工具是万能的,iostat 也不例外。它在“系统级”的 I/O 监控上很强大,但深入一步就会力不从心。这里整理一下我的常用搭档组合。8.1 进程级定位:pidstat 和 iotopiostat 告诉你系统整体 I/O 情况,但如果想知道具体哪个进程在产生 I/O,就要用pidstat -d或者iotop。前者按进程显示读写速率,适合脚本化采集;后者类似 top 的交互界面,适合人工观察。对比起来,我写脚本排查时偏好 pidstat,手动登录机器时偏好 iotop。8.2 延迟细节追踪:iostat 看不到的长尾如果需要更精确的延迟分布,iostat给不了。/proc文件系统里的io信息可以辅助,但更直接的是用blktrace、fio这类专业工具。fio可以主动压测磁盘性能,blktrace可以追踪 I/O 请求在内核里的整个旅程。不过这两个工具学习成本稍高,一般只有深挖问题时才用得着。8.3 配合监控平台长期采集日常巡检我建议写一个脚本,定期把iostat -x的采样结果落到监控平台,保留历史数据。因为很多 I/O 问题是慢慢劣化的,比如磁盘坏道逐渐增多、SSD 写入放大越来越严重,这些都是量变到质变的过程。没有历史数据,你很难说清楚“这个延迟是不是最近才变高的”。9. 一个小技巧:用 iostat 做磁盘选型和容量规划除了排障,iostat 还能帮你做一件很有价值的事——用真实业务负载来评估磁盘选型。比如你计划给新服务配存储,不确定该用高性能 SSD 还是普通 HDD,与其听厂商宣传,不如在当前机器上模拟业务负载跑一遍。方法是:先在测试环境用fio模拟业务的 I/O 模式(随机读写还是顺序读写,块大小多少,队列深度多少),再用iostat -x采集实际表现。比如业务是典型的 4KB 随机读,队列深度 32,那你就用 fio 按这个参数压测,然后对比 iostat 里的await和%util,看这台磁盘能否承受预期的 IOPS。我个人经验:不要盲目看标称 IOPS,厂商给的数字通常是最优条件下的极限值,真实环境能达到标称的 30% 到 50% 就算不错。iostat 配合 fio 的数据,比厂商宣传页可靠得多。10. 后续还能怎么扩展iostat 只是 Linux 性能分析工具箱里的一个成员。如果你发现磁盘没问题,但服务还是慢,那就要去排查网络(nicstat)、内存(vmstat)、CPU 上下文切换(pidstat -w)了。性能问题的排查思路是“先全局后局部,先系统后进程”,iostat 承担的是全局第一棒,跑好这一棒,后续方向才不会偏。我在实际使用中最深的一个体会是:工具再熟悉,也不如对业务场景的理解重要。同样的await=20ms,在 OLTP 数据库上可能是灾难,在批量分析任务里可能完全能接受。所以拿到 iostat 数据之后,一定要回到业务视角去判断“这个值对我来说到底算不算高”。