磁盘I/O监控实战:从iostat到故障排查的完整方法

发布时间:2026/10/21 5:57:18
磁盘I/O监控实战:从iostat到故障排查的完整方法
在公司做过几年性能排查我养成一个习惯新环境上线前第一件事不是看CPU核数够不够而是先摸一遍磁盘I/O的底细。很多故障表面上五花八门——接口超时、数据库连接打满、应用无响应——查到最后有相当一部分根因都落在磁盘I/O上。磁盘I/O监控这个事说难不难不就是装个工具看几个数字嘛但真到出问题的时候很多人对着iostat一屏数字完全不知道先看哪个。这篇文章我把这几年用下来的监控思路、工具组合、阈值设置经验一次性说清楚尽量少讲理论多讲能直接落地的实操。1. 磁盘I/O监控到底在解决什么问题1.1 你最可能遇到的三类磁盘假死场景先说个我印象特别深的案例。某天下午业务方反馈系统变慢登录都要转好几秒。我上去一看CPU和内存都挺正常负载也不高但整个服务就是迟钝。后来用iostat一查%util已经打到接近100%await飙到几百毫秒明显是磁盘扛不住了。这种CPU空转磁盘拖后腿的情况如果你只盯着系统负载看很难找到方向。磁盘I/O问题通常有三类典型场景第一类是吞吐瓶颈比如大数据量导出、日志集中写入、备份任务叠加磁盘带宽被打满所有读写请求都在排队。第二类是延迟突刺平时延迟很低一到某个时间段就飙高通常是定时任务、日志切割、批量任务和高峰期请求撞在一起。第三类是单点故障某块盘性能劣化或者RAID降级整条链路被拖慢业务层感受到的是偶发超时。这三种场景的共同点是表面症状都在应用层但根因都在存储层。所以监控磁盘I/O的核心价值不是让你天天盯着曲线图看而是出了问题的时候能快速判断是不是磁盘的锅以及是哪块盘、哪个进程在搞事。1.2 监控磁盘I/O不等于只盯着磁盘满了很多人一听磁盘监控第一反应是看磁盘剩余空间。说实话空间告警当然重要但I/O监控和空间监控是两码事。空间满好用df看一眼就知道I/O出问题是磁盘明明还有大量空闲空间但读写性能已经烂到没法用。举一个生活中的类比空间监控相当于看停车场还剩多少个车位I/O监控相当于看车辆进出停车场的速度。车位充足但出入口堵死了车一样进不来。运维里很多假死故障就是这种情况——磁盘没用满但队列堵死了。所以磁盘I/O监控真正要解决的是这几个问题磁盘的繁忙程度到底多高还有多少余量可以扛业务增长。请求的响应速度是否正常是持续高延迟还是偶发突刺。具体是哪个进程在大量读写是业务程序还是备份任务在抢资源。历史趋势如何有没有规律性的峰值时段。下面我按这个思路把指标、工具、排查链路逐一讲透。2. 先看懂这些核心指标再去折腾工具2.1 一秒内搞懂 iostat 的输出逻辑监控磁盘I/O最常用的工具就是iostat几乎每个Linux发行版都自带或者一条命令就能装。我第一次用iostat的时候看到满屏英文缩写也是一脸懵后来发现它的输出逻辑其实很简单就三层信息。第一层是CPU统计%user、%system、%iowait这些%iowait表示CPU等待I/O完成的时间占比。这个值高了说明CPU在等磁盘干活是最直观的磁盘可能有问题的信号。但要注意高iowait不一定就是磁盘坏了也可能是内存不足导致的大量换页判断的时候要结合其他指标。第二层是设备利用率也就是每个磁盘分区的统计核心字段是tps、kB_read/s、kB_wrtn/s、await、%util。这就是我们要重点盯的部分。第三层是分区的读写量统计一般看整个磁盘设备就行分区级别的意义不大。2.2 那些让人犯迷糊的指标逐一拆开说tps每秒传输次数可以理解为磁盘每秒处理了多少个I/O请求。注意它不等于读写吞吐量一次请求可能只读几KB也可能读几MB。看tps要和吞吐量结合单看tps高不代表流量大。kB_read/s、kB_wrtn/s每秒读写数据量这是衡量吞吐的。这里有个经验值机械盘顺序写的吞吐上限大概在150-200MB/s左右SSD看型号通常500MB/s起步NVMe可以到2GB/s以上。如果吞吐长时间贴着上限磁盘就是瓶颈。await平均每次I/O请求的处理时间单位毫秒。这是最值得盯的一个指标。机械盘正常情况下await在几个毫秒到十几毫秒如果飙到几十甚至上百毫秒说明请求在排队磁盘处理不过来了。SSD的await通常很低零点几到几毫秒如果SSD的await超过几十毫秒基本可以断定有问题。%util设备繁忙度也就是磁盘有百分之多少时间在处理请求100%表示整个采样周期内磁盘一直没闲着。这里有个大坑要提醒%util在SSD上很容易虚高因为SSD支持并行处理多个请求util打到100%并不代表性能到极限反而是吞吐和延迟更能说明问题。我见过有人拿着SSD的100% util慌慌张张来问其实业务完全没受影响。svctm每次I/O的服务时间。这个指标在新内核里基本没有实际意义了因为它计算的是平均服务时间而在现代块设备层有合并、队列调度等多层机制算出来的值参考价值不大。很多老教程还在教人看svctm可以直接忽略。2.3 我最常用的快速体检命令组合平时给一台机器做磁盘I/O体检我一般固定跑这几条命令iostat -x 1 5-x显示扩展统计信息1秒采样一次共采集5次。跑完看最后几次的平均值不要看第一次因为第一次显示的是系统启动以来的累计平均值参考意义不大。iostat -d -k 2 3-d只看设备-k以KB为单位2秒一次采集3次。这个组合适合快速看吞吐量变化。如果是定位到某块盘异常我会加-p参数按分区看iostat -x -p sda 1 5只看sda这块盘的分区统计输出更清爽。还有个容易忽略的小技巧iostat的采样间隔最好不要小于1秒因为磁盘指标本身是累计值采样间隔太短算出来的瞬时值抖动很大看起来全是毛刺反而不利于判断趋势。3. 工具选型与实操过程实录3.1 iostat 实操三组必知参数iostat是整个磁盘I/O监控里最核心的工具没有之一。它的参数看起来多常用就几个我按使用频率排个序。第一个是上面提过的-x输出扩展数据。这里面的rrqm/s和wrqm/s代表每秒合并的读/写请求数量。合并是什么意思就是把多个相邻的小请求合成一个大请求再发给磁盘。机械盘喜欢大请求合并越多性能越好但如果合并数量突然变得异常大有可能是伴生了大量小文件随机写反而要警惕。第二个是-m以MB为单位输出比默认的KB更直观。高吞吐场景下用KB看数字位数太多换成MB一眼就知道有没有贴近磁盘上限。第三个是-y跳过启动以来的累计数据直接显示采样周期内的数据。加上这个参数第一屏就有参考价值不用浪费一次采样。我常用的完整命令是iostat -xmy 1 5一次拿到CPU等待、设备util、吞吐、延迟全套数据建议直接存成alias。提示-x和-m在有些老版本里不能同时用如果报错就分开跑新版本没这个问题。3.2 iotop 看进程维度iostat能告诉你磁盘忙不忙但回答不了谁在让它忙这个问题。这时候用iotop。iotop的用法很像top动态刷新显示每个进程的I/O读写速率。两个关键字段是DISK READ和DISK WRITE单位是字节每秒一眼就能看出哪个进程在大量读写。我常用的参数iotop -o -P-o只显示有I/O操作的进程不显示那些全零的进程输出干净很多-P以进程而非线程为单位显示。如果不加-P默认会把进程的每个线程都列一遍输出非常乱。iotop需要root权限这是它唯一的门槛。有些生产环境不允许随便上root那就用下面说的pidstat。3.3 pidstat 按进程定位pidstat是另一个定位进程级I/O的好工具它不像iotop那样动态刷新而是按采样周期输出适合脚本化采集。pidstat -d 1 5-d显示I/O统计1秒采样5次。输出的kB_rd/s、kB_wr/s分别表示该进程每秒的读写量cswch/s表示上下文切换次数可以侧面反映进程的I/O阻塞情况。pidstat的输出是日志式的一行一个采样点不会覆盖屏幕方便重定向到文件做历史分析。这是它在脚本场景下的最大优势。iotop能实时看到结果但不好留存pidstat正好互补。3.4 sar 长时间采集如果故障是偶发的比如每天固定某个时段出现一次你不可能24小时盯着屏幕等它出现。这时候需要sar。sar是sysstat包里的工具配合cron任务做定时采集。配置方法很简单安装sysstat包。确保/etc/cron.d/sysstat里的定时任务在运行默认每10分钟采集一次。历史数据默认保留7天配置文件在/etc/sysstat/sysstatHISTORY参数控制保留天数。查看历史I/O数据用sar -d -f /var/log/sysstat/saXXsaXX是某天的数据文件日期是当月第几天。比如今天15号就看sa15。-d输出设备级别的tps和吞吐还可以加-p显示设备名而不是设备编号。结合sar -q看负载、sar -w看上下文切换可以把故障时段的前后情况完整还原出来。sar的10分钟粒度对看趋势和规律够用但抓偶发尖刺还是不够细。如果知道故障大概在几点可以提前用nmon或者写个循环采集脚本把粒度缩到秒级。这就是另一套玩法了后文会讲。3.5 短时峰值抓取有时候故障时间很短一两次采样就被冲过去了。我处理这种问题的方式是写一个快速采集脚本后台运行遇到指标超过阈值就持续记录while true; do iostat -xmy 1 1 | grep -A1 sda /tmp/iostat_history.log date /tmp/iostat_history.log sleep 1 done这个脚本简单粗暴但有两点要注意。一是别在生产环境长时间跑日志增长很快磁盘没被业务打挂先被监控日志打挂了二是要配合nohup或者systemd服务跑别因为终端退出就断了。更专业的做法是装一个轻量级的监控agent配置好采集周期自动落盘这里不展开说具体厂商了原理都是类似的定时采集指标、存本地、告警时候拉出来看。4. 一个真实排查案例的全过程记录4.1 现象描述有一次某系统的数据库响应突然变慢业务方反馈写入接口超时比例明显上升但又不是完全不可用属于能干活但干活很费劲的状态。我先看了系统负载和CPU负载不高CPU还有大量空闲内存也够这就让我更怀疑是磁盘。4.2 排查链路第一轮先用iostat确认磁盘状态iostat -xmy 1 10输出里%util一直在95%以上await平均80毫秒左右w_await写请求平均等待时间超过120毫秒w_tps写请求的每秒次数倒是不高大概两三百。这个组合非常典型写请求不多但每个都很慢说明不是吞吐打满而是某个环节在阻塞写请求。第二轮定位进程。用iotop一看有个日志归档的进程占了将近70%的写带宽。继续查这个进程在写什么文件发现它在把一批历史日志从本地盘拷贝到另一块盘。第三轮查为什么这个操作会阻塞主业务的写请求。看两块盘在iostat里的状态源盘和主业务盘不是同一块但目标盘恰好和数据库的数据文件在同一块物理盘上。归档进程的大量顺序写把目标盘的队列占满了数据库的随机写请求全部排队。4.3 最终定位根因就是备份/归档任务和数据业务共用了同一块物理磁盘。逻辑上它们是独立的分区甚至独立的文件系统但物理上共享同一个盘片和控制器谁都不能独善其身。这里有个很常见的认知误区分区是独立的I/O性能却不是独立隔离的。就像一栋楼的几个房间各自独立但供水管道是共用的一个房间狂放水其他房间水压就会变小。4.4 处理方案与后续短期方案把归档任务的时间窗口从业务高峰期挪到凌晨低峰期立刻缓解冲突。长期方案给归档任务换挂载点让它落到独立的存储设备上从物理层隔离同时给归档任务配置I/O优先级限制用ionice把它降到idle级别ionice -c 3 -p pid-c 3表示idle调度级别只有当磁盘空闲时才会执行这个进程的I/O操作。这个命令对机械盘效果明显SSD上效果差一些因为SSD没有机械臂寻道的概念I/O调度器的作用机制不一样。处理完之后我再跑了一遍iostatawait回落到10毫秒以内%util只有20%出头业务方反馈接口响应恢复正常。5. 告警阈值设置与监控误区的避坑经验5.1 怎么设置阈值不误报也不漏报告警阈值这个事我给不了你一个适用于所有环境的固定数字因为不同存储介质、不同业务的正常水位差异太大了。但我可以给你一套设置思路。第一步先跑一段时间的基线采集。新环境至少观察一周用sar把每天的I/O曲线摸出来搞清楚业务高峰和低峰的上下边界。别一上来就设置阈值你连正常水位是多少都不知道设出来一定瞎报。第二步按指标类型分别设置。%util建议设两个档警告线80%、严重线95%但SSD环境要谨慎参考延迟为主await建议警告线30毫秒机械盘、严重线50毫秒SSD可以压到10毫秒和30毫秒tps和吞吐的阈值要根据业务量设置最好用相对值——比如连续5分钟超过平时峰值的1.5倍就告警。第三步告警一定要带上下文。比如磁盘sda util持续5分钟超过95%这个告警价值远高于磁盘util过高。还能顺手把当时top I/O进程的信息一起带出来排查的人一看就知道该干什么。注意单次采样超标不要告警磁盘指标瞬时抖动很常见连续3-5个采样点超标再触发误报率能降一大半。5.2 日志与历史数据保留监控不只是实时看数更是为了事后回溯。我吃过一次亏当时一个I/O问题持续了几天但是没有保留历史数据等我去查的时候故障已经过去了连个对比的基线都没有。后来我就养成了习惯sysstat的HISTORY参数调大至少保留30天# 编辑 /etc/sysstat/sysstat HISTORY30同时把关键指标的每日汇总单独存一份比如每天0点跑一个脚本把当天的iostat平均数据追加到一个CSV文件里。这样月度复盘的时候直接拉出来看趋势不用去翻几十个sa文件。5.3 需要注意的几个坑第一个坑用%util判断SSD性能。前面说过SSD支持并行I/Outil到100%不代表极限。我见过一块NVMe盘util长期99%但业务延迟始终保持在1毫秒以下完全没问题。判断SSD性能优先看延迟和吞吐不要被util吓到。第二个坑忽略I/O调度器的影响。Linux默认的调度器对不同介质有不同表现机械盘用mq-deadline或者bfq通常更好NVMe盘用none也就是noop反而减少开销。如果发现I/O性能不符合预期先看看调度器设的是什么改调度器往往比换硬件还立竿见影。# 查看当前调度器 cat /sys/block/sda/queue/scheduler第三个坑文件系统层面和块设备层面的混淆。有些I/O慢其实是文件系统的问题比如inode耗尽、目录项缓存压力大、日志模式导致的写放大iostat看不出来要用df -i看inode使用率用dmesg看文件系统报错。排查I/O问题别只盯一个工具分层看才完整。第四个坑别把iowait等同于磁盘故障。iowait高可能的原因是内存不足导致换页频繁也可能是某进程在疯狂读写还可能只是CPU在等待锁。看到iowait高第一反应应该是去看内存空不空、哪个进程在写而不是直接下磁盘坏了的结论。结尾多年排查下来的一点体会做了这么多年性能排查我最大的体会是磁盘I/O监控不是靠某一个神奇工具而是靠一套实时查看、进程定位、历史回溯的组合打法。iostat负责告诉我磁盘现在忙不忙iotop和pidstat负责告诉我谁在让它忙sar负责告诉我这种忙是不是有规律。三个工具各管一段配合起来基本能覆盖日常90%以上的I/O排查场景。最后再分享一个小技巧看完指标的疑似情况别急着下结论先看一眼dmesg和系统日志。磁盘硬件层面的报错、文件系统只读切换这些信息在 iostat 里看不出来但往往才是最要命的。把工具输出和系统日志对照着看判断的准确率会高很多。