uptime 显示平均负载是 30,但你打开 top 一看,CPU 空闲率还有 80% 以上。这种"负载高、CPU 闲"的组合最让人困惑:负载不是应该反映 CPU 忙不忙吗?为什么对不上?很多人因此误判为"系统没问题,负载显示错了",结果业务其实一直在慢,只是慢在别的地方。
这篇文章要拆开来讲:Linux 的平均负载(load average)到底统计了什么、它为什么能和 CPU 使用率不一致、以及用 top、vmstat、iostat、ps 这些工具如何把"看不见的等待"挖出来。核心结论先给出来——负载统计的是"正在运行 + 不可中断等待"的任务数,其中不可中断等待多半是磁盘 IO。所以负载高而 CPU 闲,八成是 IO 卡住了。
读完这篇,你应该能在看到负载异常时,先不慌着扩容,而是用一条清晰的路径判断:到底是 CPU 排队(D 状态和 R 状态比例)、还是磁盘在拖、还是别的什么在内核里卡着。
一、平均负载的真正定义
很多人以为 load average 是"CPU 使用率",其实不是。它的准确定义是:在最近 1 分钟、5 分钟、15 分钟里,处于可运行状态(R)和不可中断睡眠状态(D)的进程数量的平均值。
拆开看这两类:
- R(Running/Runnable):正在 CPU 上跑,或者已经在运行队列里等着被调度。这类多,说明 CPU 不够用。
- D(Uninterruptible Sleep):进程在等某个不可中断的内核事件,最常见的就是等磁盘 IO 完成。这类进程不能被信号杀死,
kill -9也无效。
关键就在 D 状态。磁盘 IO 慢的时候,发起读写的进程会进入 D 状态一直等,这个等待时间被算进了负载,但它并没有消耗 CPU。于是出现"负载高、CPU 闲"的经典现象。
三个数字的含义也不同:1 分钟值反映瞬时压力,15 分钟值反映长期趋势。如果 1 分钟值远高于 15 分钟值,说明是刚发生的突发;如果三个值都高且贴得很近,说明压力是持续性的。
二、怎么判断是 CPU 排队还是 IO 等待
这是全文最核心的判断。方法很简单:看负载高的同时,CPU 的 %wa(IO 等待)高不高,以及有没有大量 D 状态进程。
| 现象组合 | 含义 | 主要根因 | 优先动作 |
|---|---|---|---|
负载高 + %wa 高 + 大量 D 态 |
IO 瓶颈 | 磁盘慢、IO 打满、存储抖动 | 查 iostat、iotop |
负载高 + %us/%sy 高 + 大量 R 态 |
CPU 瓶颈 | 计算密集、线程过多 | 查进程 CPU 占用 |
负载高 + %wa 不高 + 无明显进程 |
可能是虚拟化/内核卡顿 | 宿主机影响、NFS 挂载卡住 | 查存储、查挂载 |
| 负载高 + D 态集中在某进程 | 单一进程 IO 异常 | 该进程读写模式有问题 | 定位该进程并分析 |
| 负载低但业务慢 | 不是负载问题 | 应用层、网络、锁 | 转应用与网络排查 |
判断口诀:先看 %wa,再看 D 态,两者挂钩就是 IO。
三、动手诊断的完整命令序列
# 第一步:确认负载与 CPU 概况
uptime
# 输出示例:load average: 28.50, 26.10, 20.30
# 结合核数看:nproc 显示 8 核,那 28 的负载明显偏高
nproc # 查看 CPU 核数,用来和负载值对比
# 第二步:看 CPU 各态占比,重点是 wa 和 id
top
# 按 1 展开逐核,看是整体高还是个别核高
# 关注 Cpu(s) 行里的 wa(等待IO)和 id(空闲)
# 或直接取一次快照
top -bn1 | head -5
# 第三步:vmstat 看 r 队列和 b 队列(b 就是阻塞在IO的进程数)
vmstat 1 10
# procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu-----
# r b swpd free buff cache si so bi bo in cs us sy id wa st
# 2 18 0 120000 34000 560000 0 0 9800 7600 800 2200 8 5 60 27 0
# b=18 说明有 18 个进程阻塞在不可中断状态,wa=27 说明 27% 时间在等 IO -> 磁盘瓶颈
vmstat 的 b 列是关键指标,它直接对应负载里的 D 状态贡献。
# 第四步:定位是哪个进程在等 IO
# 找出 D 状态进程
ps -eo pid,stat,wchan,comm | awk '$2 ~ /D/'
# 或用 top 按状态过滤,也可用 ps 排序
ps -eo pid,ppid,stat,wchan:20,comm,args | grep -E ' D| D<'
# wchan 会显示进程卡在哪个内核函数上,能看到具体等待点
# 第五步:确认磁盘是否打满
iostat -x 1 5
# 关注 %util(接近100%表示磁盘饱和)、await(平均IO响应时间,毫秒)
# 再看 r/s w/s 吞吐,以及 aqu-sz(平均队列长度)
# 需要 sysstat:
# RHEL/CentOS/Rocky
dnf install -y sysstat
# Debian/Ubuntu
apt install -y sysstat
# 第六步:看具体是哪个进程在疯狂读写
iotop -oP
# 只显示有实际 IO 的进程,-P 只显示进程不显示线程
# 或从 /proc 里看进程的 IO 统计
cat /proc//io
# 关注 read_bytes 和 write_bytes
如果 iostat 显示某块盘 %util 长期 100%,就是它的问题。这时候再看是哪个进程、读哪个文件,往往能找到根因——比如某个日志疯狂落盘、某个备份任务在跑、数据库刷脏页太频繁。
四、常见的几类根因和处理
根因一:磁盘本身性能不足。
机械盘 IOPS 只有一百多,SSD 能到几万甚至几十万(经验值,取决于型号和接口)。如果业务从机械盘升级前就跑在机械盘上,随机读写一多就容易打满。解决方向是换 SSD/NVMe、上 RAID、把热数据放内存缓存,或者做读写分离。
根因二:某个进程的 IO 模式很糟糕。
比如日志框架没开缓冲,每条日志都 fsync;或者程序在做大量小文件随机读写。这类问题改代码或配置最有效,比如日志分级、批量写、异步刷盘。
# 追踪某进程的 IO 相关系统调用
strace -f -e trace=read,write,fsync,fdatasync -p 2>&1 | head -50
# 如果看到海量 fsync,就是同步刷盘太频繁
根因三:NFS 或网络存储卡顿。
挂载的网络存储在链路抖动时会大量进程进入 D 状态,负载飙高而本地 CPU 很闲。排查用 mount | grep nfs 看挂载点,nfsstat -c 看客户端统计。这类故障往往伴随"卡住几秒又恢复"的周期性抖动。
# 查看 NFS 挂载及参数
mount | grep -i nfs
# 查看 NFS 是否 soft/hard 挂载,hard 挂载在网络中断时会让进程永久 D 住
cat /proc/mounts | grep nfs
根因四:内存不足导致换页。
如果 vmstat 里 si/so(swap 换入换出)不为零,说明内存在换页,磁盘也会被拖慢,形成"内存不足→换页→IO 高→负载高"的链条。这时候真正的根因是内存不够。
free -h
vmstat 1 5 # 看 si/so 是否持续非零
五、危险的排查与修复动作
排查过程中有几步容易出事故,务必注意:
关于 D 状态进程:D 状态进程无法被 kill -9 杀死,因为它不响应信号。如果你看到某个 D 状态进程卡了很久,说明底层 IO 一直没返回。此时真正要解决的是 IO 存储,而不是强行杀进程(也杀不掉)。如果存储彻底坏了,可能需要重启机器。
关于 swap:临时关掉 swap 可以用 swapoff -a,但这会把已换出的页全部读回内存,如果内存本来就不够,会直接触发 OOM,甚至把系统搞崩。风险极高,非必要不要在内存紧张时执行。回滚用 swapon -a。更安全的做法是先确认 free -h 的余量,再在维护窗口操作。
关于重启:D 状态进程堆积时,systemctl restart 或 reboot -f 可能挂住。带 -f 强制的重启有丢数据风险,生产环境慎用。重启前尽量先定位到是哪个存储设备的问题。
关于调整 IO 调度器:可以把调度器从 cfq(老内核)或 mq-deadline 换成 none(NVMe 常用)来降低延迟。
# 查看当前调度器
cat /sys/block/sda/queue/scheduler
# 临时切换(sudo 权限)
echo none > /sys/block/nvme0n1/queue/scheduler
# 永久生效:在内核启动参数加 elevator=none,或写 udev 规则
# 回滚:写回原值,如 echo mq-deadline > /sys/block/xxx/queue/scheduler
风险提示:调度器切换会影响所有该设备上的 IO,对数据库类延迟敏感业务影响明显,务必在维护窗口逐台验证,记录原值以便回滚。
常见问题
Q:负载多少算高?有没有统一标准?
没有绝对值。判断基准是 CPU 核数:8 核机器负载长期 8 左右属于"刚好跑满",持续超过 16(约两倍核数)就要警觉。但这是经验值,最关键的还是结合 %wa 和业务延迟一起判断。
Q:为什么 top 里 CPU 空闲很多,负载却有几十?
因为负载把 D 状态(不可中断等待)的进程也算进去了,这些进程在等磁盘或网络存储,不消耗 CPU。CPU 闲、负载高,几乎可以锁定是 IO 或存储等待。
Q:D 状态进程 kill 不掉怎么办?
D 状态进程不响应任何信号,kill -9 也无效,这是内核设计使然。不要反复尝试杀它,应该去查它等的是什么存储,等 IO 恢复后它会自然退出。如果是存储彻底故障,才考虑重启。
Q:负载是 15 分钟平均,那实时怎么看?
uptime 只有 1/5/15 分钟三个值。要看实时,用 vmstat 1 看 r 和 b 两列的瞬时值,或 sar -q 1 看运行队列和负载的实时趋势。
Q:虚拟机上负载很高,但宿主机看着正常,怎么解释?
虚拟机的负载统计的是虚机内部视角,宿主机上看到的负载是全局的。虚机负载高可能是自身 IO 打到宿主机存储后,被宿主机层排队("IO 窃取"),这时要在宿主机上查该虚机的 IO 情况。
总结
平均负载 = 可运行任务 + 不可中断等待任务,它不是 CPU 使用率。负载高而 CPU 闲,最主要的原因是大量进程在 D 状态等 IO。
诊断顺序固定:uptime/nproc 判断高低 → top 看 %wa → vmstat 1 看 b 列(阻塞进程数)→ ps -eo stat,wchan 找具体 D 状态进程 → iostat -x/iotop 确认哪块盘、哪个进程。
对症处理分四类:磁盘性能不足就升级存储,IO 模式差就改应用配置,NFS/网络存储卡顿就查链路和挂载参数,内存不足引起换页就先加内存。
危险操作要谨慎:D 状态进程杀不掉也不该硬杀,swapoff -a 和强制重启都可能造成数据丢失或系统崩溃,必须先确认内存余量和根因。
记住判断口诀:先看 %wa,再看 D 态,两者挂钩就是 IO,方向对了排查才快。
企业QQ咨询




