资讯动态

Linux磁盘I/O性能排查:iostat核心指标与实战解析

发布时间:2026/10/21 15:12:30 来源:尧图企业网站定制
做服务器性能排查的人基本都经历过这样的场景业务方跑过来说接口变慢了、数据库查询卡了、应用超时率上来了你登录到机器上第一件事是什么看负载、看 CPU、看内存这些都是常规操作。但很多时候你转了一圈发现 CPU 和内存都挺正常问题却还是没解决。这时候大部分人容易忽略的关键一环就是磁盘 I/O。Linux 下分析磁盘 I/O 性能iostat 是我用得最多、也最顺手的一个工具没有之一。它不像某些监控工具要装一堆依赖系统自带、输出稳定、参数清晰一条命令就能把磁盘的吞吐、IOPS、响应时间、队列情况全部摆在桌面上。这篇内容适合刚入门、想搞清楚系统瓶颈的运维新手适合部署了数据库、消息队列、大数据集群后需要定期看存储健康度的平台工程师也适合那些被业务方追着问“为什么接口变慢”的应用开发者。iostat 能解决的核心问题听起来很简单但做扎实了非常有用磁盘到底忙不忙有多忙瓶颈在哪个盘延迟是设备本身的物理极限还是因为排队太严重被人为放大弄明白这些问题你才能拿着数据去和基础设施团队、云厂商或者硬件供应商进行有效对话。1. 为什么偏偏是 iostat1.1 磁盘性能问题为何难排查磁盘性能问题之所以比 CPU、内存问题难搞核心在于它的链路太长。一个 I/O 请求发出去要经过应用层、文件系统、块设备层、驱动、磁盘固件最后才真正落到盘片上中间任何一层出问题表现都是“慢”但你光靠看应用日志根本无法定位问题到底出在哪。而且磁盘的“慢”还分好几种。有的是吞吐不够比如大量顺序读磁盘带宽被打满有的是 IOPS 不够比如高并发随机读写每秒处理不了那么多请求有的是响应时间变大单个请求延迟从几毫秒涨到几十毫秒甚至上百毫秒还有的是因为排队太多明明设备本身能力还行但请求全堵在队列里。这些问题如果不借助工具靠肉眼看负载是看不出来的。负载高也可能是因为某种异常进程在大量计算而磁盘可能完全空闲。更麻烦的是很多业务系统对磁盘延迟的感知是滞后的。比如数据库连接池里的连接一旦因为 I/O 超时被标记为不可用恢复起来需要时间消息队列里的堆积不会立刻反映在业务指标上但会慢慢侵蚀整个集群的健康状态。等你真正感受到业务影响的时候磁盘问题往往已经持续了一段时间。所以我需要一个工具能快速回答三个问题哪个盘有问题是读还是写问题是吞吐型、IOPS 型还是延迟型iostat 就是干这个的。1.2 iostat 的定位与不可替代性系统自带的性能工具其实不少vmstat 能看 CPU、内存和部分 I/O 数据sar 能历史回溯dstat 能实时展示多种指标但这些工具在磁盘维度上都做不到 iostat 这么专注和深入。vmstat 的 bi/bo 只是简单的块读写量完全不区分设备也无法反映延迟和队列sar 虽然有 -b 和 -d 参数输出格式偏报表化实时排查时不够直观。iostat 的核心优势在于它直接读取内核块设备层的统计数据并且在每个设备维度上完整呈现 IOPS、吞吐量、平均等待时间、服务时间、队列长度、利用率等指标。它不依赖任何外部监控系统单机就能用输出一眼能看懂。尤其在做性能容量评估的时候iostat 的 -x 扩展输出几乎是行业事实标准做存储选型、云盘规格评估、数据库实例规格规划大家默认都是拿 iostat 的数据来对比。我个人的经验是iostat 属于“平时不起眼、关键时刻保命”的工具。当整个集群出现雪崩、应用集体超时、监控面板一片飘红的时候别的工具也许还在慢慢加载依赖iostat 已经在几秒钟内帮你锁定问题盘和 I/O 方向了。1.3 安装、版本与最基础用法iostat 属于 sysstat 软件包。大多数发行版默认没有安装但安装非常简单Debian/Ubuntu 系apt install sysstatRHEL/CentOS 系yum install sysstat极简容器或特殊系统可以用pidstat或直接读取/proc/diskstats替代安装完成后直接执行iostat会输出两段内容一段是从开机到现在的平均统计CPU 和磁盘一段是最近一次采样周期内的统计。但说实话直接用默认输出做排查意义不大因为你很难从中看到波动趋势。实际使用中几乎都用下面这组参数iostat -d -x -k 1 3这条命令的含义是只看磁盘设备-d输出扩展详细信息-x以 KB 为单位展示-k每 1 秒采样一次共输出 3 次。第一次输出是所有采样周期的平均值后两次才是真正有价值的实时数据。实际工作中我通常把次数拉长到 5 到 10 次用几秒钟时间观察一个稳定的 I/O 波形这比单看一次输出要靠谱得多。2. 核心指标逐个拆解从内核计数器到设备健康度2.1 iostat 的数据从哪来要真正读懂 iostat必须知道它的数据源头。Linux 内核在块设备层维护了一组计数器位置在/sys/block/$device/stat同时/proc/diskstats也会提供同样格式的数据。iostat 本质上就是周期性读取这些计数器计算差值并换算成各种指标。这些计数器的核心字段包括读完成次数、读合并次数、读扇区数、读耗时毫秒、写完成次数、写合并次数、写扇区数、写耗时、正在进行的 I/O 数、I/O 总耗时、I/O 加权耗时。注意“合并”这个概念Linux 内核会把相邻的、可以合并的小 I/O 合并成一个大 I/O 再下发这样能显著提升机械硬盘和 SSD 的吞吐效率。所以你在 iostat 里看到的 tps是设备层实际处理的 I/O 次数已经包含了合并后的结果。明白这一点很重要因为很多人在对比应用层监控和 iostat 数据的时候会发现“对不上”。应用明明每秒发了上千次写请求iostat 显示的 tps 却只有几百这通常不是漏统计而是内核把大量相邻小请求合并了。理解了这个机制你就不会错误地怀疑工具出了问题。2.2 几个关键列的真正含义在iostat -x的扩展输出里你最需要关注的列并不多但每一列都代表不同的性能维度rrqm/s和wrqm/s每秒合并的读、写请求数。这个值高说明 I/O 模式比较连续文件系统层做了有效的合并通常意味着吞吐会比较好。r/s和w/s每秒实际下发的读、写请求次数对应 IOPS 概念。这是衡量随机小 I/O 能力的重要指标。rkB/s和wkB/s每秒读、写的数据量对应吞吐概念。机械盘的顺序吞吐和随机吞吐完全不同SSD 也要区分运行状态。await平均每次 I/O 从发起到完成的总耗时单位毫秒。这个值是应用感知延迟的核心指标它包含了排队时间。svctm平均每次 I/O 的服务时间可以理解为设备真正处理请求花费的时间。这个指标在较新的内核版本中已经不太被推荐使用因为它只是一个估算值。%util设备繁忙率或者说设备队列非空的时间占比。举个例子假设某块盘的await从 2ms 突然涨到 80ms同时%util显示接近 100%说明磁盘确实忙不过来了。如果await很高但%util只有 20%情况就完全不同了——要么是请求本身触发了很多额外的内部操作要么是设备有其它原因导致响应变慢。不同的指标组合指向不同的排查方向。2.3 %util 最大的误解关于%util有个流传很广的误解很多人把它直接理解为“磁盘利用率 80% 说明还能再撑 20% 的负载”这个理解在大多数场景下是错的。%util的真实含义是在采样周期内设备有 I/O 请求在排队或处理的时间占比。它是个布尔化的累加值不是精细的利用率。假设一块硬盘每个 I/O 处理时间刚好是 10ms采样周期 1 秒内即使只有 100 个请求%util也可能显示 100%因为每个 I/O 之间几乎无缝衔接。但这 100 个请求可能只是这块盘能力的十分之一。反过来如果请求下发很密集但每个请求都是微秒级完成%util可能看起来只有 30%但实际 IOPS 也可能已经非常高了。所以判断磁盘是否真的到了极限一定要结合%util、r/s w/s、await以及设备本身的规格指标一起来看。单看%util是 100% 就下结论“磁盘满了”非常容易误判。3. 常用参数组合与实战输出解读3.1 先记住这组黄金参数如果你只想记住一组 iostat 命令我推荐下面这个iostat -d -x -k 1 5你可能会问为什么不加-m用 MB 展示因为用 KB 展示的时候小数点后的精度更高对小文件的读写观察更灵敏。在大多数业务系统里单盘吞吐达到每秒几百 MB 就已经属于高负载场景了用 MB 单位会丢失部分细节。还有一个我经常用的变体是加上-t参数让每次输出的前面带上时间戳iostat -d -x -k -t 1 5加了-t之后你能把 iostat 的输出和应用的日志时间、报警时间对应起来。这种时间对齐在排查问题的时候特别重要比如你拿到一条应用报错记录说“14:32:10 数据库连接超时”这时候如果 iostat 输出里 14:32:08 附近的await恰好飙高证据链就闭环了。3.2 -x 扩展字段逐个过很多人不敢用-x觉得字段太多看不懂。实际上-x的输出非常有规律按“读、写、总计”三个方向展开每条线都有对应的指标。我们用一张表快速过一遍常用字段字段含义排查中的价值rrqm/s, wrqm/s每秒合并的读/写请求数判断是否存在大量可合并的连续 I/Or/s, w/s每秒下发的读/写请求数IOPS对比设备标称 IOPS 能力判断是否打满rkB/s, wkB/s每秒读/写吞吐KB对比设备带宽能力判断吞吐型瓶颈avgrq-sz平均请求大小扇区数区分随机小 I/O 和顺序大 I/Oavgqu-sz平均队列长度队列越长说明拥堵越严重await平均响应时间含排队应用延迟感知的核心指标r_await, w_await单独看读/写的平均响应时间定位是读慢还是写慢svctm平均服务时间估算值参考即可不要过度依赖%util设备繁忙时间占比结合其它指标一起看勿单独下结论avgrq-sz这个字段容易被忽略但它非常能说明问题。如果它长期在几十扇区以下一扇区 512 字节说明磁盘处理的大多是随机小 I/O如果几千到上万扇区说明是顺序大 I/O。这个区分直接决定了你该往哪个方向优化随机小 I/O 瓶颈看 IOPS 和队列深度顺序大 I/O 瓶颈看带宽和块大小。3.3 采样与持续监控技巧iostat 的输出是周期性采样后计算差值得到的所以采样间隔很关键。间隔太短比如 0.1 秒容易看到大量抖动噪声很大间隔太长比如 60 秒又会错过高峰瞬间问题容易被平均淹没。我常用的策略是先短后长第一次排查用 1 秒间隔、连续 10 次快速观察基本波形发现问题区间后再用 0.5 秒间隔在短时间内做精细化采样。还有一种更省心的做法是把 iostat 做成后台日志采集nohup iostat -d -x -k -t 1 60 /tmp/iostat_$(date %Y%m%d_%H%M%S).log 21 这样每小时采集一次现场数据保留下来。事后复盘的时候这份日志比任何事后猜测都更有说服力。我曾经靠一份凌晨的 iostat 日志成功定位了一个只在业务低峰期出现的定时任务导致的 I/O 抖动那个定时任务每天凌晨跑全量数据校验单次运行时间不长但每次都把磁盘延迟拉高三倍。没有持续采样的日志这种“幽灵抖动”根本抓不到。4. 真实场景实操三种典型瓶颈的定位过程4.1 场景一数据库服务器持续高延迟某公司的数据库实例近期持续出现慢查询报警CPU 和内存都很充裕但查询延迟从均值 5ms 涨到了 80ms。登录机器后我先跑了一组采样命令iostat -d -x -k -t 1 5观察输出sda这块数据盘的%util长时间在 95% 以上w/s大约 1200wkB/s大约 40000w_await从正常的 3ms 涨到了 60ms 上下avgqu-sz接近 40。这些指标组合起来说明写 IOPS 已经打满了这块盘的处理能力请求大量排队队列深度高所以每个请求的等待时间被显著放大。进一步确认我用iostat -d -x 1 1配合pidstat -d 1 5定位到具体的写进程。最终发现是数据库的 binlog 和 redo log 放在了同一个数据盘上业务高峰期写入量大日志刷盘和随机数据页写入相互竞争。优化方案很简单把日志文件迁移到单独的 SSD 卷上数据盘只承担数据页读写。迁移之后同样的业务高峰期w_await稳定回落到 4ms 以内。这个场景的关键点在于不要只盯着%util一个数字要看await和avgqu-sz的组合。如果%util高但await不高、avgqu-sz小说明设备处理能力还有余量只是主动性繁忙只有当await显著升高、队列堆积的时候才能确认是真正的瓶颈。4.2 场景二写入量不大但磁盘却满负荷还有一次排查很有意思业务方说写入量很小但磁盘持续繁忙。我执行 iostat 采样看到的输出是wkB/s只有 3000 左右w/s却高达 2500%util接近 100%avgrq-sz只有 4 个扇区左右。这个组合暴露了问题的本质单次写入极小平均才 2KB 左右但每秒写入次数极高。这就是典型的随机小 IOPS 瓶颈。磁盘的 IOPS 能力是有限的即使每秒钟写的数据量加起来并不大只要请求次数够多照样能把设备的处理能力压垮。这种情况下优化方向就不是“减少数据量”而是“减少请求次数”。我后续的排查发现这个应用在为每一行数据单独执行更新操作没有做批量提交。和研发确认后把多个更新合并成批处理提交w/s从 2500 降到了 300同样的数据量下磁盘负载瞬间降下来了。这个问题给我们的教训是看 I/O 性能不能只看吞吐IOPS 的维度同等重要很多时候“量的减少”远不如“次数的减少”来得有效。4.3 场景三多盘机器如何快速找出问题盘现在的服务器普遍会挂多块盘系统盘、数据盘、日志盘、备份盘各司其职。当整个系统变慢的时候你能看到整体的%util很高但必须要快速定位到具体是哪块盘拖了后腿。这里我有个习惯先跑一条不带过滤的iostat -d -x -k 1 3让所有设备全部输出。然后在脑子里快速做一个排序重点关注%util高和await高交叉出现的设备。有时候问题盘并不明显因为一块盘显示出高%util但await正常另一块盘%util只有 40%但await异常高。后者反而可能是“有内鬼”的那块盘因为它的高延迟往往是内部重试或者异常状态导致的。定位到可疑盘之后我会用iostat -d -x -k 1 10 | grep sdb单独跟踪那块盘。同时用iostat -N -d -x -k 1 3查看 LVM 逻辑卷或设备映射的名称方便和挂载点对应起来。很多新手容易卡在这一步搞不清楚sda、sdb、dm-0到底对应哪个挂载目录实际上用lsblk和df -h交叉确认一下三五秒就能搞清楚。5. 常见误区、避坑经验与交叉验证5.1 五个经典误区第一个误区是把%util当成利用率百分比。前面已经详细说过它只是设备繁忙时间占比不代表剩余能力。第二个误区是只看iostat一次输出就下结论没有连续采样。磁盘 I/O 是高度突发的一次采样恰好采到谷值或峰值都会误导判断。第三个误区是忽略“合并”这个机制把应用层看到的请求数和 iostat 里的r/s、w/s直接对比然后怀疑工具不准。第四个误区是排障时不关注采样间隔。有些人在业务高峰期用iostat 60 1每隔一分钟才采样一次瞬间的高峰自然会被平均掉问题就永远“看不到”。正确的做法是根据业务特点选择合适的采样密度宁可多采几次不要漏掉关键峰值。第五个误区是在发生 I/O 问题的时候只盯着存储设备本身的型号和规格忽略了文件系统层面的因素比如日志模式、挂载参数、预读设置等。工具只能帮你定位到“设备层很忙”但忙的原因可能在更上层的文件系统或应用设计里。5.2 排查思路与心得用了这么多年 iostat我总结出来一套自己的排查顺序在这里分享给各位。拿到一台出现 I/O 问题的机器我通常按这样的顺序走第一步用iostat -d -x -k -t 1 10拿到基础数据确认设备总体状态第二步找出%util偏高或者await异常的设备对比该设备的型号和标称性能指标第三步用pidstat -dsysstat 工具包里的另一个命令定位到具体进程确认是不是业务进程在产生大量 I/O第四步看具体的 I/O 模式通过avgrq-sz、r/s w/s、rkB/s wkB/s的组合判断是随机还是顺序、是读还是写、是 IOPS 型还是吞吐型第五步基于模式判断给出临时应对手段和长期优化建议。这套流程的核心思想是不要陷入工具本身而要带着“是什么模式、谁在打、打在哪”这三个问题去看数据。iostat 的好用之处恰恰在于它把每个维度的数据都摆在明面上你只需要有一点点耐心去组合判断。5.3 交叉验证工具链iostat 不是万能的它擅长的是看设备层结果但对于“为什么会产生这样的 I/O”这种问题必须和其它工具配合。我自己的常用组合是这样的iostat 负责看设备层指标pidstat -d负责看进程级 I/Ovmstat 1负责看系统整体内存、CPU 和 I/O 的联动关系top或htop负责看进程资源竞争。如果需要看文件系统维度的延迟分布可以用fatrace或者在特定版本内核下用bcc-tools里的biosnoop、iolatency这类工具做追踪。有几个很典型的交叉验证场景。比如 iostat 显示%util很高但pidstat却找不到明显的写进程这时候需要考虑是不是页缓存回收、内存压力导致的写回或者是不是文件系统在后台做日志提交。这种问题光靠 iostat 是看不出来的需要结合vmstat里的si、so来判断是否存在内存换页再结合文件系统层的配置来做判断。再比如 iostat 显示读延迟很高但业务侧主要是写入操作。这种情况可能不是磁盘物理问题而是因为读取触发了缺页或者文件系统预读机制可以看看rrqm/s是否异常高同时用blktrace或者perf做下采样分析。每次排查完我都会把 iostat 的原始输出和结论一起存档量的积累多了以后你再看到类似的数据模式几乎能立刻判断出问题方向。6. 一些实在的使用细节有几个细节我在实践中反复踩过坑最后补充给各位。一个是关于svctm。这个指标在一些较老的文章里被当成衡量磁盘速度的核心指标但现代内核已经不推荐使用它了因为它是个估算值对 SSD 和 NVMe 设备意义不大。如果你看到某篇文章还在用svctm做核心判断依据那套方法论大概率是十年前的经验需要打个折扣。另一个是-m参数和-k参数的选择。有人习惯用-m看 MB因为数字好看。但如果你的系统里单盘吞吐在几十 MB 以下-m会显示小数点后的很多位反而不好读。我个人的习惯是默认-k只在明确需要按 GB 级别观察大吞吐的时候才切到-m。还有一个容易被忽略的参数是-y。默认情况下iostat 的第一次输出显示的是系统启动以来的平均统计很多人在排障的时候忘了跳过第一次直接看后面几次结果就拿着一个包含历史平均值的数字去分析当前问题自然会觉得“数据对不上”。加上-y可以跳过第一次的全历史输出让后续采样全部是周期内的真实数据。最后我再说一个习惯。每次遇到存储相关的变更比如换云盘类型、改文件系统挂载参数、调整数据库刷盘策略我都会在变更前和变更后各跑一组iostat -d -x -k -t 1 10把前后数据放在一起对比。这个习惯已经帮我发现了至少三次配置变更引起的性能回退。工具本身很简单但把它用成一种固定的工作习惯你会慢慢发现自己对系统性能的判断越来越准。希望这份 iostat 使用总结能帮你在下次排查磁盘性能问题时少走一些弯路。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑