cpu 等待时间久,但使用率低,怎么排查(随手记)
CPU load high,但 CPU usage low,说明系统“排队的人很多”,但不一定都在真正吃 CPU。Linux 的 load average 统计的是:
可运行状态 R 的进程 + 不可中断睡眠状态 D 的进程
所以 CPU 使用率低但 load 高,最常见原因是:大量进程卡在 I/O、磁盘、NFS、网络存储、锁等待、D 状态。
一、先确认 load 是否真的高
先看 CPU 核数:
nproc
再看 load:
uptime
例如:
load average: 20.00, 18.00, 15.00
如果机器是:
nproc = 32
那 load 20 不一定严重。
但如果机器只有 4 核,load 20 就说明队列严重堆积。
二、先看整体 CPU 状态
top
重点看这一行:
%Cpu(s): 2.0 us, 1.0 sy, 0.0 ni, 90.0 id, 7.0 wa, 0.0 hi, 0.0 si, 0.0 st
重点字段:
| 字段 | 含义 |
|---|---|
| us | 用户态 CPU |
| sy | 内核态 CPU |
| id | 空闲 |
| wa | I/O wait |
| st | 虚拟化偷走的 CPU 时间 |
如果你看到:
CPU idle 很高
load 很高
那重点怀疑 D 状态进程 / I/O 卡住。
如果看到:
wa 很高
那基本是磁盘、文件系统、NFS、数据库 I/O 问题。
如果看到:
st 很高
说明是云主机宿主机资源争抢,CPU 被 steal 了。
三、找 D 状态进程
这是最关键的一步。
ps -eo state,pid,ppid,comm,wchan:32,cmd | awk '$1=="D"'
或者:
ps aux | awk '$8 ~ /D/'
如果有大量 D 状态进程,说明它们卡在不可中断睡眠,通常是磁盘、NFS、块设备、内核 I/O 等问题。
例如输出:
D 1234 mysqld io_schedule /usr/sbin/mysqld
D 2345 nginx nfs_wait_bit nginx: worker process
看 wchan 很有用:
| wchan 关键词 | 可能原因 |
|---|---|
| io_schedule | 磁盘 I/O 等待 |
| nfs_wait | NFS 卡住 |
| xfs / ext4 | 文件系统问题 |
| jbd2 | journal 写入卡住 |
| blk_mq | 块设备层等待 |
| futex | 锁等待,不一定是 I/O |
四、看哪些进程贡献了 load
用 top 之后按:
Shift + H
显示线程。
或者直接:
ps -eo pid,ppid,state,pcpu,pmem,wchan:32,cmd --sort=-pcpu | head -30
再看所有 R / D 状态:
ps -eo pid,ppid,state,pcpu,pmem,wchan:32,cmd | awk '$3=="R" || $3=="D"'
如果很多是 R,说明确实在排 CPU。
如果很多是 D,说明是 I/O 或内核等待。
五、重点看磁盘 I/O
安装有 sysstat 的话:
iostat -x 1
重点看:
| 字段 | 判断 |
|---|---|
| %util | 接近 100%,磁盘忙满 |
| await | I/O 平均等待时间,高说明慢 |
| r/s、w/s | 每秒读写次数 |
| rkB/s、wkB/s | 每秒读写量 |
| aqu-sz | 队列长度 |
如果看到:
%util 99%
await 200ms
说明磁盘 I/O 已经成为瓶颈。
没有 iostat 可以用:
vmstat 1
重点看:
r b si so bi bo us sy id wa st
解释:
| 字段 | 含义 |
|---|---|
| r | 正在等待 CPU 的进程数 |
| b | 不可中断睡眠进程数,通常是 I/O |
| wa | I/O wait |
| bi/bo | 块设备读写 |
如果:
b 很高,wa 高
就是 I/O 卡住。
六、看哪个进程在疯狂读写磁盘
iotop -oPa
如果没有 iotop:
pidstat -d 1
关注:
kB_rd/s
kB_wr/s
iodelay
例如:
pidstat -d 1
可以看出是 MySQL、Java、Nginx、备份脚本还是日志写入导致 I/O 堵塞。
七、检查是否是 NFS / 网络存储卡住
如果机器挂载了 NFS、Ceph、GlusterFS、云盘、NAS,很容易出现 CPU 不高但 load 飙升。
查看挂载:
mount | grep -E "nfs|ceph|gluster|fuse"
查看磁盘:
df -h
注意:如果 df -h 自己都卡住,基本高度怀疑某个挂载点异常。
也可以看:
dmesg -T | tail -100
常见报错:
nfs: server not responding
I/O error
blocked for more than 120 seconds
task xxx blocked
EXT4-fs error
XFS error
八、检查是否有大量 blocked task
dmesg -T | grep -i "blocked for more than"
或者:
dmesg -T | grep -Ei "hung|blocked|I/O error|reset|timeout|nfs|ext4|xfs"
如果看到:
INFO: task mysqld:1234 blocked for more than 120 seconds
说明某些进程在内核里卡死等待,load 会升高,但 CPU 不一定高。
九、看是否内存不足导致 swap / 回收
CPU 低、load 高也可能是内存压力导致大量进程等待内存回收或 swap。
free -h
再看:
vmstat 1
关注:
si so
如果 si/so 持续不为 0,说明在换入换出 swap。
查看内存压力:
sar -B 1
或者:
cat /proc/meminfo
重点看:
MemAvailable
SwapFree
Dirty
Writeback
如果 Dirty、Writeback 很高,说明大量脏页在等写盘,也可能导致 load 高。
十、看是不是容器 / cgroup CPU 被限制
如果是在 Docker / Kubernetes 里,经常会出现:
容器内 CPU usage 不高
但是 load 高
可能是 CPU quota 限制、throttling。
Docker 看:
docker stats
容器内看:
cat /sys/fs/cgroup/cpu.stat 2>/dev/null
cat /sys/fs/cgroup/cpu/cpu.stat 2>/dev/null
关注:
nr_throttled
throttled_time
如果一直增加,说明容器被 CPU 限速。
K8s 可以看:
kubectl top pod
kubectl describe pod <pod>
十一、一个比较实用的排查顺序
你可以按这个顺序来:
uptime
nproc
top
然后:
vmstat 1
如果 b 高、wa 高,继续查 I/O:
iostat -x 1
iotop -oPa
pidstat -d 1
如果 wa 不高,但 load 还是高,查 D 状态:
ps -eo state,pid,ppid,comm,wchan:32,cmd | awk '$1=="D"'
再查内核日志:
dmesg -T | grep -Ei "blocked|hung|I/O error|timeout|reset|nfs|ext4|xfs"
十二、快速判断表
| 现象 | 可能原因 |
|---|---|
| load 高,CPU idle 高 | 大量 D 状态进程 |
| load 高,wa 高 | 磁盘 / 存储 I/O 慢 |
| load 高,b 高 | 进程阻塞在 I/O |
| load 高,st 高 | 云主机 CPU 被宿主机抢占 |
| load 高,si/so 高 | swap 严重 |
| df -h 卡住 | 挂载点异常,常见 NFS/NAS |
| dmesg 有 blocked 120s | 内核等待,通常是 I/O 或驱动问题 |
| 容器里 load 高 | CPU quota / cgroup throttling |
最常见的结论是:
CPU usage low + load high
不是 CPU 算力不够,
而是大量进程在等 I/O、等磁盘、等网络存储、等内核资源。
你重点先跑这三个命令:
vmstat 1
ps -eo state,pid,ppid,comm,wchan:32,cmd | awk '$1=="D"'
dmesg -T | grep -Ei "blocked|hung|I/O error|timeout|nfs|ext4|xfs"
基本就能判断大方向。
更多推荐


所有评论(0)