引言:Load Average 高不等于 CPU 忙

线上告警群里最常见的误判之一,就是"Load Average 高了 → CPU 爆了 → 加机器"。但很多时候,你 top 一看 CPU 明明很空闲,负载却飙到十几。这一篇把 Load Average 的来龙去脉讲透:它到底是什么、什么时候会虚高、以及如何一步步定位真正的瓶颈。

一、Load Average 到底是什么

Load Average(负载平均值)是过去 1/5/15 分钟处于 可运行态不可中断睡眠态 的进程平均数量。注意是两个状态:

  • R 状态(Running/Runnable):正在 CPU 上跑,或排队等 CPU 的进程
  • D 状态(Uninterruptible Sleep):不可中断睡眠,通常是等磁盘 IO、等网络 IO、等锁的进程

这就是为什么负载高不一定 CPU 忙——如果一堆进程卡在 D 状态等磁盘,CPU 空闲但负载照样爆表。判断标准:负载值 ≈ CPU 核数算正常,超过核数 70% 算偏高,持续超过核数 2 倍属于严重告警。

二、第一板斧:确认 CPU 还是 IO

# 同时看 CPU 和负载top -bn1 | head -5# CPU 空闲率很高但负载很高 → 大概率不是 CPU 瓶颈# 看平均负载的三个值uptime

关键判断口诀:CPU 空闲 + 负载高 = 查 IO;CPU 打满 + 负载高 = 查进程。用 vmstat 一步确认:

vmstat 1 5

重点看三列:r(运行队列,等待 CPU 的进程数)、b(阻塞队列,D 状态进程数)、wa(CPU 等待 IO 的时间占比)。如果 bwa 很高而 r 不高,基本可以断定是 IO 瓶颈。

三、第二板斧:定位罪魁祸首

确认是 CPU 问题后,找出吃 CPU 的进程:

top -c -o %CPU# 或ps aux --sort=-%cpu | head -15

确认是 IO 问题后,找出在等 IO 的进程:

# 列出所有 D 状态进程ps -eo pid,stat,wchan:32,cmd | awk '$2 ~ /^D/'# wchan 显示进程阻塞在内核的哪个函数上,能直接看出在等什么# 用 iostat 看具体哪块盘在忙iostat -x 1

iostat -x 里重点看 %util(磁盘利用率)和 await(平均 IO 等待时间)。%util 接近 100% 说明磁盘已饱和。如果所有盘都不忙,那可能是 NFS、分布式存储等网络文件系统在拖后腿——D 状态进程的 wchan 会指向网络相关函数。

四、第三板斧:分清瞬时尖峰与持续高位

Load Average 的 1/5/15 分钟三个值很有讲究:

  • 1 分钟高、15 分钟低:瞬时尖峰,比如定时任务集中执行、编译、备份,通常不用太紧张
  • 1 分钟低、15 分钟高:负载正在下降,说明之前的瓶颈正在缓解
  • 三个值都高且接近:持续过载,必须认真对待

遇到瞬时尖峰,用 atopsar -q 回看历史负载曲线,确认尖峰的时间规律:

sar -q -f /var/log/sa/sa$(date -d yesterday +%d)# 查看昨天的负载记录,配合 cron 任务时间表对照

如果是 cron 集中执行导致,用 systemd-timer 的 RandomizedDelaySec 或给 cron 加随机偏移,把任务打散。

五、常见误判场景复盘

场景1:内存不足引发的"假 CPU 忙"

内存不够时,系统疯狂换页(swap in/out),CPU 大量消耗在内存回收上,表现为 CPU 高 + 负载高,但业务进程本身并不吃 CPU。此时 free -h 会看到 swap 使用量在涨。解法是加内存或优化内存占用,而不是加 CPU。

场景2:D 状态进程堆积导致负载虚高

某个进程挂起在不可中断睡眠(比如 NFS 断连、磁盘故障),负载会一直居高不下,且 kill 都杀不掉(D 状态进程无法被普通信号杀死)。此时要先恢复底层存储,再考虑重启进程。

场景3:短时高并发被误读

促销、秒杀等短时流量高峰,1 分钟负载冲到很高但 5/15 分钟正常。只要响应时间可接受,无需扩容,重点是观察 5 分钟均值是否回落。

六、结语:先定性,再定量,最后动手

排查 Load Average 的正确姿势是:先看三个时间窗口的数值判断是尖峰还是持续过载 → 用 vmstat 区分 CPU 瓶颈还是 IO 瓶颈 → 用 ps/top/iostat 定位具体进程和盘 → 最后才是扩容或优化。顺序一旦搞反,很容易加错资源,钱花了问题还在。把这套流程写进团队的故障排查手册,比任何监控大屏都管用。