云服务器磁盘 I/O 飙高?从 iostat 到进程定位的排查顺序

举报
yd_275727902 发表于 2026/11/07 09:25:04 2026/11/07
【摘要】 一、场景:机器“卡”了,CPU 却不高线上云服务器偶尔会出现这样的情况:SSH 登录变慢,接口响应时间从几十毫秒涨到几秒,但 top 里 CPU 的 us、sy 并不高,负载(load average)却明显升高。这类现象很多时候指向同一个方向:磁盘 I/O 成了瓶颈。Linux 的 load average 不仅统计正在运行和等待 CPU 的进程,也统计处于不可中断睡眠(D 状态)的进程...

一、场景:机器“卡”了,CPU 却不高

线上云服务器偶尔会出现这样的情况:SSH 登录变慢,接口响应时间从几十毫秒涨到几秒,但 top 里 CPU 的 us、sy 并不高,负载(load average)却明显升高。这类现象很多时候指向同一个方向:磁盘 I/O 成了瓶颈。

Linux 的 load average 不仅统计正在运行和等待 CPU 的进程,也统计处于不可中断睡眠(D 状态)的进程,而 D 状态大多是在等待 I/O。所以“负载高、CPU 闲”是磁盘问题的典型信号。

排查磁盘 I/O 问题,建议按“先确认是不是 I/O → 再定位哪块盘 → 再定位哪个进程 → 再定位哪个文件 → 最后找根因”的顺序进行,避免一上来就重启服务或扩容。

二、排查顺序

第 1 步:用 top / vmstat 确认 I/O 等待

先看 top 第三行的 wa(iowait):

%Cpu(s):  3.1 us,  1.8 sy,  0.0 ni, 60.2 id, 34.5 wa,  0.0 hi,  0.4 si,  0.0 st

(以上为示意输出)

wa 表示 CPU 空闲且存在未完成磁盘 I/O 的时间占比。它偏高说明有进程在等盘,但要注意:wa 只是一个间接指标,CPU 忙的时候 wa 反而可能被“压低”,所以不能只凭它下结论。

再用 vmstat 1 连续观察:

vmstat 1 5
procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu-----
 r  b   swpd   free   buff  cache   si   so    bi    bo   in   cs us sy id wa st
 1  6      0 512000  20480 3100000    0    0   120 85000 1500 2200  3  2 61 34  0

(以上为示意输出)

重点看几列:

  • b:处于不可中断睡眠的进程数,持续大于 0 值得关注;
  • bi / bo:每秒从块设备读入 / 写出的块数;
  • si / so:每秒换入 / 换出的内存量,如果不为 0,要怀疑是内存不足导致的 swap I/O;
  • wa:与 top 中含义一致。

第 2 步:用 iostat -x 定位是哪块盘

iostat 属于 sysstat 包,没有的话先安装(如 yum install sysstat 或 apt install sysstat)。

iostat -x 1
Device   r/s    w/s   rkB/s    wkB/s  r_await w_await aqu-sz  %util
vda      2.0    3.0    16.0     40.0     0.8     1.2    0.01    0.6
vdb     15.0  1800.0  240.0  72000.0     5.3    48.7   87.60   99.8

(以上为示意输出,已省略部分列)

各列含义:

  • r/s、w/s:每秒完成的读、写请求数,即实际 IOPS;
  • rkB/s、wkB/s:每秒读、写的数据量,即吞吐;
  • r_await、w_await:读、写请求的平均耗时(毫秒),包含在队列中排队的时间和设备服务时间;旧版本只有一个合并的 await;
  • aqu-sz:平均队列长度(旧版本叫 avgqu-sz),持续偏大说明请求在排队;
  • %util:设备有 I/O 在处理的时间占比。

两点需要特别说明:

  1. svctm 已被去掉。较新版本的 sysstat 已不再输出 svctm,因为它是推算值、并不可靠,不要再拿它当“磁盘服务时间”来判断。
  2. %util 在 NVMe、SSD 和很多云硬盘上不可靠。这类设备能并行处理多个请求,%util 只表示“这段时间里至少有一个请求在处理”,到 100% 不代表设备已经饱和。判断是否饱和,应结合 await 是否明显升高、aqu-sz 是否持续偏大,以及 IOPS / 吞吐是否接近云硬盘规格上限。

上面的示意中,vdb 写请求多、w_await 高、队列长,可以初步判断是 vdb 上的写入压力过大。可以用 lsblk 或 df -h 确认该盘挂载在哪个目录。

第 3 步:用 pidstat / iotop 定位进程

找到盘之后,下一步是找“谁在读写”。

pidstat -d 1
UID    PID   kB_rd/s   kB_wr/s  kB_ccwr/s  iodelay  Command
0     2345      0.00  68000.00       0.00      120  java
999   1888     12.00    800.00       0.00        5  mysqld

(以上为示意输出)

kB_rd/s、kB_wr/s 是进程每秒读写量;iodelay 是进程等待块 I/O 的延迟(以时钟节拍计),可以帮助发现“写得不多但等得很久”的进程。

也可以用 iotop(需 root 权限):

iotop -oPa

参数含义:-o 只显示有实际 I/O 的进程,-P 按进程而不是线程显示,-a 显示累计量而不是瞬时速率。累计模式适合观察一段时间内谁写得最多,能抓住间歇性的写入。

第 4 步:查 D 状态进程

ps -eo stat,pid,cmd | awk '$1~/D/'

输出中 STAT 列包含 D 的进程处于不可中断睡眠,通常在等 I/O。如果这类进程长期存在且数量不少,基本可以确认 I/O 是瓶颈。必要时可以看 cat /proc/<pid>/stack(需 root)了解它卡在内核哪个调用上。

第 5 步:定位进程在读写哪些文件

确定进程后,看它打开了哪些文件:

lsof -p <pid>

重点关注日志文件、数据文件、临时文件。再看进程累计 I/O 统计:

cat /proc/<pid>/io
rchar: 1203345
wchar: 9876543210
read_bytes: 40960
write_bytes: 9871234048
...

(以上为示意输出)

rchar/wchar 是进程通过 read/write 等系统调用读写的字节数,包含命中页缓存的部分;read_bytes/write_bytes 才是真正落到块设备层的量。间隔几秒取两次相减,就能估算出它真实的磁盘读写速率。

第 6 步(可选):blktrace 深入分析

如果需要分析请求大小、顺序还是随机、时间消耗在哪一阶段,可以用 blktrace 配合 blkparse 或 btt 抓取块设备层事件。它开销较大、数据量多,建议短时间抓取,一般排查用不到这一步。

补充:排查时的几个注意事项

  • 先保留现场再处理。在清理日志或重启进程前,把 iostat、pidstat 的输出保存下来,方便事后复盘和对比。
  • 注意区分读和写。读压力大通常与缓存命中率低、扫描类查询有关;写压力大更多与日志、刷盘策略、批量导入有关,两者的优化方向不同。
  • 观察要有时间跨度。I/O 问题常常是周期性的,例如定时任务每小时触发一次,只看一两秒的数据容易漏掉,可以用 sar -d 查看 sysstat 采集的历史数据。
  • 不要只看单机。同一个应用如果多台机器同时出现问题,更可能是业务流量或公共依赖变化引起的,而不是某块盘本身故障。

三、常见原因与处理

1. 日志暴涨
应用开启了 DEBUG 日志、异常堆栈循环打印,都会造成大量写入。处理:调整日志级别,配置 logrotate 按大小切割和压缩,日志尽量与数据放在不同的盘上。

2. 磁盘或 inode 写满
空间接近写满时,文件系统分配效率会下降;df -h 看空间,df -i 看 inode。大量小文件(如会话文件、缓存碎片)可能导致 inode 用尽,空间还剩但无法创建新文件。处理:清理过期小文件并找出产生它们的程序。

3. 内存不足导致 swap I/O
vmstat 中 si/so 持续不为 0,说明系统在频繁换页,磁盘压力其实来自内存不足。处理:用 free -h、top 按内存排序找出占用大的进程,优化内存或升配,而不是盲目换更快的盘。

4. 云硬盘性能达到上限
云硬盘按类型和容量有对应的 IOPS 和吞吐上限,部分类型还提供突发能力,突发额度用完后性能会回落到基准水平。如果 iostat 中 IOPS 或吞吐长时间贴近规格值、await 随之升高,就是触到了上限。具体数值以云厂商当前文档和控制台监控为准。处理:更换更高性能的云硬盘类型、扩容(部分类型性能随容量增长)、或把读写分散到多块盘。

5. 业务本身的 I/O 模式问题
例如数据库缺少索引导致全表扫描、备份或批量任务在业务高峰运行、小块随机写过多。处理:优化 SQL,把备份等任务挪到低峰并用 ionice 降低优先级,合并小写入。

四、小结

磁盘 I/O 排查可以按固定顺序推进:

  1. top / vmstat 看 wa、b、si/so,确认是否是 I/O 问题;
  2. iostat -x 1 看 IOPS、吞吐、await、aqu-sz,定位是哪块盘,不要单看 %util,也不要再看 svctm;
  3. pidstat -d 1、iotop -oPa 找出读写最多的进程;
  4. ps 查 D 状态进程,确认等待情况;
  5. lsof、/proc/<pid>/io 定位具体文件和真实落盘量;
  6. 结合日志、inode、swap、云硬盘规格上限分析根因。

按这个顺序,大多数“CPU 不高但机器很卡”的问题都能在较短时间内找到源头。平时也建议在云监控中为磁盘读写 IOPS、吞吐和使用率配置告警,在问题影响业务前发现它。

【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0)

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。