最让人头疼的不是服务器彻底挂掉,而是它“半死不活”——CPU占用不到10%,内存余量也充足,网络没有波动,但整台机器就像陷在沼泽里一样,SSH敲个命令要好几秒才回显,Web服务偶尔报504。跑top一看,load average已经飙到8以上,底下还蹲着一排状态为D的进程。遇到这种情况,我基本可以锁定问题出在磁盘I/O层。
这篇文章会把我在Ubuntu 22.04上排查磁盘I/O高负载的完整链路写清楚,核心工具是iotop和systemd。iotop负责帮我把“哪个进程在吃磁盘I/O”这个关键问题回答清楚,systemd则承担两个角色:既能用cgroup统计来辅助审计,又能作为限流手术刀直接抑制失控进程的I/O读写。无论你是刚接触Linux运维的新手,还是被这类问题反复折腾过的老手,这条链路都有一定的通用性。
1. 先确认“I/O高”不是错觉:量化问题再动手
很多人一遇到服务器负载高,第一反应就是跑top看CPU,发现CPU不高就开始胡乱怀疑进程,折腾一圈才发现问题在磁盘。所以我的习惯是,先花三分钟把问题量化清楚,确认I/O确实是瓶颈,再决定下一步怎么排查。
1.1 三分钟建立基线:iostat + vmstat 的组合读数
第一条命令,永远先跑iostat -x 1。iostat属于sysstat包,Ubuntu 22.04上如果没装,先apt install sysstat。
bash复制iostat -x 1
这条命令会以1秒为间隔刷新,直接打印每个块设备的详细读写情况。我最关心的几列是:
%util:设备在采样周期内有多忙。接近100%说明设备已经处于饱和状态。await:I/O请求从发出到完成的平均等待时间,包含排队时间和服务时间,单位是毫秒。这个值越高,说明请求排队越严重。rkB/s和wkB/s:每秒读写的KB数,直接反应吞吐量。r_await和w_await:读请求和写请求的平均等待时间,可以区分读慢还是写慢。
第二眼再去看vmstat 1的输出。
bash复制vmstat 1
重点看三个位置:wa列(CPU花在等待I/O上的时间百分比)、bi列(每秒从块设备读入的数据量)、bo列(每秒写入块设备的数据量)。如果wa持续超过30%,配合iostat里的%util偏高,基本可以确认I/O是当前系统的瓶颈。
另外一个值得养成习惯的动作是检查/proc/pressure/io。Ubuntu 22.04的内核默认开启了PSI(Pressure Stall Information),直接读这个文件,能看到系统由于I/O等待造成的任务停滞时间。
bash复制cat /proc/pressure/io
输出里有两个关键指标:some表示至少有一个任务因为等待I/O而停顿的时间,full表示所有任务都被I/O卡住的时间。后面跟着的是过去10秒、60秒、300秒三个时间窗口的累计数值。如果full这个值在10秒窗口里有明显涨幅,说明I/O压力已经大到影响整机响应。
1.2 区分“读写量过大”和“读写路径变慢”
iostat的读数不仅帮你确认问题,还能帮你区分I/O高负载的两种形态。这两种形态的排查方向完全不同。
| 形态 | 典型读数 | 排查方向 |
|---|---|---|
| 读写量过大 | rkB/s、wkB/s很高,%util饱和 |
找出具体进程,查为什么产生这么多读写 |
| 读写路径变慢 | await飙到几百毫秒,但rkB/s、wkB/s并不高,%util可能只有50% |
更可能涉及硬件降级、块层争抢、云盘限制 |
举个实际的例子:一台机器上跑着数据库和Web服务,wkB/s长期保持在200MB/s以上,%util一直是100%,这就是典型的“写量过大”,用iotop去抓谁在写盘就对了。但如果你看到await已经700毫秒,wkB/s却只有5MB/s,那问题多半不在进程的读写行为上,而在存储链路本身——可能是磁盘硬件故障、RAID卡策略、或者云平台底层存储排队,这时候把iotop盯到天荒地老也找不到答案。
1.3 别忽略D状态进程和PSI数据
在确认I/O瓶颈的过程中,有一个经常被忽略的信号:处于不可中断睡眠状态(D状态)的进程。这种进程正在等待I/O完成,无法被信号杀死,也无法被正常调度。如果系统里频繁出现大量D状态进程,说明它们在集体排队等磁盘。
一条命令就能列出所有D状态的进程:
bash复制ps -eo state,pid,comm | awk '$1 ~ /D/'
配合top里的wa列和iostat的await,基本能把“I/O高负载”这件事坐实。做了这一层确认之后,再上iotop去定位是哪个进程干的,排查效率会高很多,也不会在错误的路上浪费时间。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. iotop实战:从进程里把“磁盘杀手”揪出来
如果说iostat回答的是“磁盘有多忙”,那iotop回答的就是“谁让磁盘这么忙”。它是按进程维度实时展示I/O读写速率的利器,原理是读取/proc/<pid>/io的统计计数,再计算采样周期内的差值。
2.1 iotop的正确打开方式:参数组合与界面解读
Ubuntu 22.04上安装很简单:
bash复制apt install iotop
运行iotop需要root权限,因为要读取每个进程的/proc/<pid>/io文件。直接敲iotop进入的是交互式界面,类似top,会实时刷新每个进程的磁盘读写速率。但我实际工作中很少干瞪眼看交互界面,因为问题通常不是盯着能盯出来的,尤其当I/O高峰是间歇性的。
我更常用的组合是:
bash复制iotop -o -b -d 5 -k -P -t
逐个参数拆开说:
-o:only,只显示有I/O活动的进程,过滤掉那些读写了0字节的进程,让输出清爽很多。-b:ba
