共计 10273 个字符,预计需要花费 26 分钟才能阅读完成。
一文搞懂 Linux 系统负载 Load Average 到底怎么看
问题背景
服务器突然变慢、SSH 登录卡顿、业务接口响应时间上升——这些场景几乎每个运维工程师都遇到过。很多人的第一反应是 ” 负载太高了 ”,然后跑去查 CPU、查进程。但其实大多数人对 Linux Load Average 的理解是模糊的——3 个数字到底什么意思?数值到多少算高?和 CPU 使用率是什么关系?为什么 top 显示 CPU 使用率不高,但 Load Average 却很高?
这些问题的答案直接影响故障判断的方向。如果把 Load Average 和 CPU 使用率混为一谈,很可能会在排查时走错方向——明明是 IO 瓶颈,你却盯着 CPU 不放。
这篇文章面向初中级 Linux 运维工程师,系统讲解 Load Average 的计算机制、三个数字的真正含义、和 CPU/IO 的关系、以及在故障排查中的实际用法。文章内容基于 Linux 4.x 及以上内核,所有结论都可以通过 Linux 自带命令验证,不需要特殊工具。
核心概念:什么是 Load Average
1.1 教科书式的定义
Linux 的 Load Average 是 在过去 1 分钟、5 分钟、15 分钟内,系统中处于可运行状态(Running)和不可中断等待状态(Uninterruptible Sleep)的平均进程数量。
这个定义里有几个关键点:
一、” 可运行状态 ”(Running):在 Linux 中,进程状态分为几种。Running 状态意味着进程正在 CPU 上运行,或者已经准备好等待 CPU 分配。这部分进程会参与 Load Average 计算。
二、” 不可中断等待状态 ”(Uninterruptible Sleep)”:这个状态也叫 D 状态(ps 或 top 显示为 D),指进程正在等待 IO 操作完成(磁盘、网络等),而且这个等待是 不可中断 的——信号无法打断。比如进程在等待磁盘 IO 返回时,会进入 Uninterruptible Sleep。
这就是 Load Average 和 CPU 使用率最大的区别:CPU 使用率只统计正在使用 CPU 的进程,而 Load Average 还包括那些在等待 IO 的进程。这就是为什么有时候你看到 CPU 使用率只有 30%,但 Load Average 却很高——大量进程在等待磁盘 IO。
** 三、” 平均 ”**:Load Average 不是瞬时值,而是过去一段时间的平均值。它用指数加权移动平均算法计算,越近的数据权重越大,但历史数据也有影响。这也是为什么它有 1 分钟、5 分钟、15 分钟三个数字。
1.2 Load Average 的三个数字到底什么意思
执行 uptime 或 top,会看到类似这样的输出:
$ uptime
10:15:32 up 45 days, 3:22, 2 users, load average: 3.52, 2.85, 2.60
三个数字的含义:
load average: 3.52, 2.85, 2.60
───── ───── ─────
1 分钟 5 分钟 15 分钟
-
3.52(1 分钟):过去 1 分钟系统的平均负载 -
2.85(5 分钟):过去 5 分钟系统的平均负载 -
2.60(15 分钟):过去 15 分钟系统的平均负载
数值本身的单位是 ” 进程数 ”,不是百分比。3.52 意味着在过去 1 分钟内,平均有 3.52 个进程在 CPU 上运行或等待 IO。
1.3 怎么判断 Load Average 是否过高
网上流传一个 ” 经验公式 ”:Load Average 不应该超过 CPU 核心数。这个说法只对了一半。
如果是纯 CPU 密集型负载:Load Average 接近 CPU 核心数是正常的(比如 8 核 CPU,Load Average 在 8 左右)。
如果是 IO 密集型负载:Load Average 远高于 CPU 核心数是正常的(比如 8 核 CPU,Load Average 可能达到 50,但 CPU 使用率可能只有 20%)。
正确的判断方式:
# 查看 CPU 核心数
nproc
# 或
grep "processor" /proc/cpuinfo | wc -l
# 结合 Load Average 和 CPU 使用率一起看
uptime
# 如果 Load Average > CPU 核心数,且 top 显示 CPU 使用率不高,说明是 IO 瓶颈
# 如果 Load Average > CPU 核心数,且 top 显示 CPU 使用率也很高,说明是 CPU 瓶颈
# 如果 Load Average < CPU 核心数,且 CPU 使用率不高,说明系统资源充裕
实际场景举例:
场景一:8 核 CPU,Load Average = 2.5,CPU 使用率 = 20%
判断:系统很轻松,几乎没有负载
场景二:8 核 CPU,Load Average = 12.0,CPU 使用率 = 15%
判断:IO 瓶颈,大量进程在等待磁盘或网络 IO
场景三:8 核 CPU,Load Average = 8.5,CPU 使用率 = 95%
判断:CPU 瓶颈,进程在排队等 CPU
场景四:8 核 CPU,Load Average = 60.0,CPU 使用率 = 95%
判断:同时有 CPU 和 IO 问题,大量进程在排队
第二步:深入理解 Load Average 的计算机制
2.1 内核如何计算 Load Average
Load Average 的计算逻辑在 Linux 内核的 kernel/sched/loadavg.c 中,使用的是 指数加权移动平均(EWMA)算法:
load(t) = a * load(t-1) + (1-a) * n
其中:
-
load(t)是当前时刻的 Load Average -
load(t-1)是上一个计算周期的 Load Average -
n是当前活跃进程数(Running + Uninterruptible Sleep) -
a是衰减系数,设置为exp(-5/60s)= 0.998
计算每 5 秒执行一次,但报告给用户空间是每 1 秒更新一次。
三个时间窗口的衰减系数:
1 分钟:a = exp(-5/60) = 0.9982
5 分钟:a = exp(-5/300) = 0.9835
15 分钟:a = exp(-5/900) = 0.9559
这就是为什么 1 分钟的 Load Average 变化最快,15 分钟的曲线最平滑。
2.2 /proc/loadavg 文件详解
Load Average 的数据来源是 /proc/loadavg 文件:
cat /proc/loadavg
# 输出格式:
# 3.52 2.85 2.60 4/1234 56789
# ───── ───── ───── ─────── ──────
# 1 分钟 5 分钟 15 分钟 运行 / 总进程数 最后一个创建的进程 ID
/proc/loadavg 的第四个字段 4/1234:
-
斜杠前的数字(4)表示当前 Running 状态的进程数 -
斜杠后的数字(1234)表示系统总进程数(包括所有状态的进程)
第五个字段(56789)是 Linux 2.6 以后引入的,代表系统创建的最后一个进程的 PID。这个数字持续增长说明系统在持续创建进程(可能是短生命周期进程)。
# 监控这个数字的变化
watch -n 1 'cat /proc/loadavg'
# 如果 PID 数字增长很快,说明有进程在不断创建 / 销毁(比如 PHP-FPM 频繁重启、某些定时任务有问题)
2.3 Uninterruptible Sleep 到底是什么
Uninterruptible Sleep(D 状态进程)是理解 Load Average 的关键。它和普通 Sleep(状态 S)的区别:
S 状态(Sleep):进程在等待某个事件,比如 sleep(2)、等待锁、等待 IO 完成。可以被信号中断,收到信号后会立即唤醒。
D 状态(Uninterruptible Sleep):进程在等待硬件 IO 完成,不可被信号中断。进程会一直等待,直到 IO 操作返回。即使 kill -9 也无法杀死 D 状态的进程(只能等 IO 操作完成或超时)。
D 状态进程的典型场景:
1. NFS 挂载后网络断开,进程在等待 NFS IO 返回
2. 磁盘 IO 非常严重,进程在等待磁盘读写完成
3. 僵尸进程在等待子进程退出(极少)
2.4 怎么查看 D 状态进程
# 方法一:top 命令
top
# 按 Shift + > 或 < 切换排序字段,找到 S 列(进程状态)
# D 状态的进程会在 S 列显示为 D
# 方法二:ps 命令
ps aux | awk '$8 ~ /D/ {print}'
# 方法三:查找处于 D 状态的进程(- STAT 列包含 D)
ps aux | grep -E 'D|STAT'
# 方法四:直接查看 /proc/<pid>/stat 中的进程状态码
# 状态码在第 3 个字段(从 1 开始计数),D=IO 等待,R= 运行,S= 睡眠
如果发现大量 D 状态进程,说明系统 IO 瓶颈严重。这个时候 Load Average 很高但 CPU 不高,排查方向应该是磁盘和网络 IO,而不是 CPU。
第三步:Load Average 和 CPU 使用率的关系
3.1 top 命令中的 Load Average 和 CPU 信息
top -bn1 | head -5
# 输出:
# top - 10:15:32 up 45 days, 3:22, 2 users, load average: 3.52, 2.85, 2.60
# Tasks: 1234 total, 4 running, 1230 sleeping, 0 stopped, 0 zombie
# %Cpu(s): 15.2 us, 3.1 sy, 0.0 ni, 81.7 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st
top 输出的 CPU 各字段含义:
us: user space - 用户空间进程(应用程序)使用的 CPU 时间
sy: system - 内核空间使用的 CPU 时间
ni: nice - nice 值被调整过的用户进程使用的 CPU 时间
id: idle - CPU 空闲时间(最关键的指标)wa: iowait - CPU 等待 IO 完成的时间(这是关键!)hi: hardware interrupts - 硬件中断
si: soft interrupts - 软件中断(网络、调度等)st: stolen - 被虚拟化 hypervisor 偷走的时间(虚拟机场景)
81.7 id 和 Load Average 3.52 的关系:
-
CPU 空闲率 81.7% 意味着只有 18.3% 的 CPU 在工作 -
Load Average 3.52 意味着平均有 3.52 个进程在等 CPU 或 IO -
如果 CPU 核心数是 8,Load Average 3.52 小于核心数,说明 CPU 资源本身很充裕 -
但 Load Average 不为 0,说明有进程在等东西——如果是 IO 等的,CPU 使用率就不会高
3.2 %Cpu(s): wa (iowait) 才是关键
iowait(wa)是 Load Average 和 CPU 使用率分道扬镳的核心指标。
iowait 表示 CPU 在等待 IO 操作完成的时间比例。如果 iowait 很高(超过 20%),说明 CPU 大量的时间在等 IO,而不是在计算。
# 查看 iowait
top -bn1 | grep -E '^%Cpu|^Cpu'
# 或用 vmstat(更直观)
vmstat 1 5
# 输出:
# r b swpd free buff cache si so bi bo in cs us sy id wa st
# 4 2 0 8000000 500000 10000000 0 0 0 0 100 200 10 5 80 5 0
# r: 运行中的进程数(相当于 Load Average 1 分钟)
# b: 不可中断睡眠的进程数(就是 Load Average 中计入的 D 状态进程)
# wa: iowait
3.3 实战:分析一个高 Load Average 场景
假设 uptime 输出如下:
load average: 12.5, 10.2, 8.0
同时 top 显示:
%Cpu(s): 10.5 us, 2.1 sy, 0.0 ni, 45.0 id, 42.4 wa
CPU 核心数:nproc = 8
分析:
-
Load Average 12.5 > CPU 核心数 8,说明系统负载偏高 -
CPU 使用率 10.5% + 2.1% = 12.6%,iowait 42.4%,idle 45% -
CPU 并不是瓶颈(只有 12.6% 在工作,45% 在 idle) -
问题在于 IO:iowait 42.4% 说明大量进程在等待 IO -
Load Average 高的原因是大量进程处于 D 状态(Uninterruptible Sleep)
下一步排查:到底是哪种 IO 在拖慢系统
# 查看磁盘 IO 统计
iostat -x 1 5
# 重点关注:
# %util: 磁盘 IO 使用率,如果 > 80% 说明磁盘是瓶颈
# avgrq-sz: 平均请求大小(扇区数)
# avgqu-sz: 平均 IO 队列长度,如果 > 1 说明 IO 队列等待严重
# await: 平均等待时间(毫秒),如果 > 20ms 说明 IO 很慢
# 查看哪个进程在大量使用 IO
iotop -oa
# 或
pidstat -d 1 5
# 如果没有 iotop,用 ps 辅助判断
ps aux | awk '$8 ~ /D/ {print $0}'
第四步:高 Load Average 的完整排查流程
4.1 第一步:确认 Load Average 是否真的过高
# 查看 CPU 核心数和当前 Load Average
nproc
uptime
# 如果 Load Average < CPU 核心数 * 0.7,问题可能不严重
# 如果 Load Average > CPU 核心数 * 2,继续排查
4.2 第二步:确认是 CPU 瓶颈还是 IO 瓶颈
# 查看 CPU 各指标
vmstat 1 5
# 判断标准:
# - iowait (wa) > 20% 且 idle (id) > 40%:IO 瓶颈
# - iowait 低且 idle 低,us (user) 高:CPU 瓶颈
# - iowait 高且 idle 也低:CPU 和 IO 都有问题
4.3 第三步:如果是 CPU 瓶颈,查找消耗 CPU 的进程
# 查看 CPU 使用率最高的进程(按 CPU 排序)
ps aux --sort=-%cpu | head -20
# 或用 top(按 CPU 排序)
top -bn1 -o %CPU | head -20
# 查看具体是哪些进程的 CPU 使用率高
# 如果是某个业务进程 CPU 使用率持续 100%,需要:
# 1. 查看该进程的线程数
ps -eLf | grep <pid> | wc -l
# 2. 查看该进程的子进程
pstree -p <pid>
# 3. 分析是单线程慢还是多线程都在忙
# 4. 如果是 Java 进程,看 GC 是否频繁
# 5. 如果是 Python/Golang,看是否有死循环或计算密集任务
4.4 第四步:如果是 IO 瓶颈,查找消耗 IO 的进程
# 用 iotop 查看 IO 占用最高的进程
sudo iotop -oa
# 如果没有 iotop,用 pidstat
sudo pidstat -d 1 5
# 查看具体是哪个磁盘在忙
iostat -x 1 3
# 查看进程的 IO 统计
cat /proc/<pid>/io
# rchar: 读的总字节数
# wchar: 写的总字节数
# syscr: 读系统调用次数
# syscw: 写系统调用次数
# read_bytes: 实际从磁盘读的字节数
# write_bytes: 实际写到磁盘的字节数
常见 IO 瓶颈场景:
场景一:大量日志写入
# 查看谁在写磁盘
sudo iotop -oa | head -50
# 发现某个 Python 进程在持续写日志,写入速度 50MB/s
# 查看该进程的打开文件
ls -la /proc/<pid>/fd | grep -v socket | grep -v pipe
# 发现写入了大量临时文件
# 解决方案:
# 1. 日志轮转(logrotate)
# 2. 异步写日志
# 3. 将日志写入 tmpfs(内存文件系统)再定期刷盘
场景二:Swap 使用导致 IO
# 查看 swap 使用
free -m
swapon -s
# 如果 Swap 已用 > 0,说明物理内存不足,系统在用磁盘做 swap
# 解决方案:
# 1. 查看哪些进程占用内存最多
ps aux --sort=-%mem | head -10
# 2. 调整 OOM Killer 策略
# 3. 增加物理内存
# 4. 限制进程内存使用(cgroup)
场景三:MySQL 大量磁盘顺序写
# 查看 MySQL 的 IO 模式
iostat -x 1 5
# 通常 MySQL 的 IO 是随机读写(InnoDB 脏页刷新)和顺序写(binlog)
# 如果 MySQL IO 很高,考虑:
# 1. 调整 innodb_flush_log_at_trx_commit(权衡安全性和性能)
# 2. 使用电池供电的 RAID 卡(BBU)来缓存写操作
# 3. 将 binlog 和数据文件放在不同物理磁盘
# 4. 调整 innodb_io_capacity 参数
4.5 第五步:排查 D 状态进程
# 查找所有 D 状态的进程
ps aux | awk '$8 ~ /D/ {print"PID:"$2" USER:"$1" CMD:"$11}'
# 查看某个 D 状态进程的详细信息
cat /proc/<pid>/stack
# 这个文件显示进程当前的内核堆栈,可以知道进程在等什么
# 查看 D 状态进程等待的 IO 设备
cat /proc/<pid>/fd/* 2>/dev/null | head -20
# 或者查看进程打开的文件描述符
ls -la /proc/<pid>/fd
# 如果某个文件描述符指向 /dev/sda1,说明在等磁盘 IO
第五步:不同场景的 Load Average 分析
5.1 场景一:Load Average 瞬间飙升
# 问题:早上 10:00 突然告警 Load Average 从 2 飙升到 20,5 分钟后恢复
# 1. 查看具体是哪个时间点
uptime
# 10:01: Load Average 20.5, 12.3, 6.0
# 10:06: Load Average 8.2, 10.5, 6.5
# 2. 查看 10:00-10:05 期间运行了什么进程
sudo ps -eo pid,lstart,cmd | grep "lstart" | awk '$2" "$3" "$4 >="10:00"&& $2" "$3" "$4 <="10:05"'
# 这个命令比较复杂,也可以用 sar 或 auditd
# 3. 用 sar 查看 CPU 和 IO 历史
sar -q 1 60 > /tmp/load.log
# %usr: 用户 CPU
# %system: 系统 CPU
# %iowait: IO 等待
# 4. 常见原因:
# - 定时任务(cron)同时启动了大量进程
# - 备份脚本在执行
# - 日志轮转(logrotate)触发
# - 某个批处理任务启动
预防措施:错峰定时任务,不要让大量定时任务在同一分钟启动。
5.2 场景二:Load Average 持续很高但 CPU 使用率不高
# 问题:Load Average 持续在 30 左右,但 CPU 使用率只有 15%
# 诊断:
vmstat 1 5
# 查看 iowait 是否很高
# 查看 D 状态进程数量
ps aux | awk '$8 ~ /D/ {count++} END {print"D state processes:", count}'
# 如果 D 状态进程数量和 Load Average 接近,说明 Load Average 主要是 IO 导致的
# 查看磁盘 IO
iostat -x 1 3
常见根因:
-
NFS/CIFS 挂载后网络或服务器响应慢 -
大量进程在等待数据库磁盘 IO -
磁盘硬件故障或 RAID 卡缓存失效 -
大量进程在等待虚拟化存储(云服务器常见)
5.3 场景三:Load Average 和 CPU 使用率都很高
# 问题:Load Average 持续 15,CPU 使用率 90%
# 诊断:
top -bn1
# 确认是哪个进程占用了 CPU
ps aux --sort=-%cpu | head -10
# 找到 CPU 占用最高的进程
# 查看该进程的详细信息
pstree -p <pid>
# 查看进程树,看是否有大量子进程
# 如果是 java 进程
jstack <pid>
# 查看 Java 进程的线程堆栈
# 如果是 nginx/php-fpm
ps -eLf | grep <pid> | wc -l
# 查看 worker 进程数
常见根因:
-
PHP-FPM 进程数设置过多 -
Java 应用出现死循环或计算密集任务 -
Python 脚本出现 GIL 竞争 -
被攻击(如 CC 攻击,导致大量请求)
第六步:监控和告警配置
6.1 基于 Load Average 配置监控告警
#!/bin/bash
# save as: check_load.sh
# 配置 cron: */5 * * * * /usr/local/bin/check_load.sh
THRESHOLD=$(nproc)
LOAD=$(awk '{print $1}' /proc/loadavg)
LOAD_INT=${LOAD%.*}
if ["$LOAD_INT" -gt "$THRESHOLD" ]; then
echo "Alert: Load Average ($LOAD) > CPU cores ($THRESHOLD)" | tee -a /var/log/load_alert.log
# 这里接入告警:钉钉 / 企业微信 / 飞书 / 邮件
fi
6.2 用 Prometheus Node Exporter 采集 Load Average
Prometheus 的 node_load* 指标可以采集 Load Average:
# Prometheus 配置中的 node_exporter job
-job_name:node
static_configs:
-targets:['localhost:9100']
relabel_configs:
-source_labels:[__address__]
target_label:instance
查询语句:
# 当前 Load Average(1 分钟)node_load1{instance="your-host"}
# 超过 CPU 核心数的比例
node_load1 / count(node_cpu{instance="your-host"})
# 如果这个值 > 1,说明 CPU 资源不足
告警规则:
# PrometheusRule
groups:
-name:node-load
rules:
-alert:NodeHighLoad
expr:node_load1/count(node_load1)>0.8
for:5m
labels:
severity:warning
annotations:
summary:"Node {{$labels.instance}} load is high"
description:"Load Average 1m = {{$value}}, CPU cores = {{$labels.cpu}}"
-alert:NodeCriticalLoad
expr:node_load1/count(node_load1)>1.2
for:2m
labels:
severity:critical
第七步:Load Average 优化实战
7.1 CPU 瓶颈优化
如果确认是 CPU 瓶颈导致 Load Average 高:
# 1. 找到 CPU 消耗最高的进程
ps aux --sort=-%cpu | head -20
# 2. 如果是业务进程
# - 水平扩展:增加进程 / 容器数量
# - 垂直优化:优化算法、减少不必要的计算
# - 热点代码优化:profiling 后针对性优化
# 3. 如果是系统进程
# - 检查是否有大量中断(cat /proc/interrupts)
# - 检查是否有大量上下文切换(vmstat 1,看 cs 列)
# 上下文切换过多的排查:
pidstat -w 1 5
# 如果某个进程的 cswch/s(上下文切换次数)非常高,说明该进程在频繁被调度
7.2 IO 瓶颈优化
如果确认是 IO 瓶颈导致 Load Average 高:
# 1. 找到 IO 消耗最高的进程
sudo iotop -oa
# 2. 如果是大量小文件 IO
# - 合并小文件写入
# - 使用 SSD
# - 使用内存文件系统(tmpfs)做缓冲
# 3. 如果是顺序写 IO
# - 调整 IO 调度算法
cat /sys/block/sda/queue/scheduler
# SSD 推荐:none (noop)
# HDD 推荐:mq-deadline 或 bfq
# 临时修改(重启失效):
echo none | sudo tee /sys/block/sda/queue/scheduler
# 永久修改:编辑 /etc/default/grub
# GRUB_CMDLINE_LINUX="elevator=none"
# 4. 如果是 Swap IO
free -m
# 如果 Swap 使用量持续 > 0,说明内存不足
# 解决方案:增加内存或限制进程内存
7.3 网络 IO 瓶颈
# 如果 Load Average 高但磁盘 IO 不高,检查网络 IO
sar -n DEV 1 5
# 查看各网卡的网络流量
# 查看 TCP 连接数
netstat -an | awk '/^tcp/ {print $6}' | sort | uniq -c
# 如果有大量 TIME_WAIT 连接
netstat -an | awk '/^tcp/ {print $6}' | grep TIME_WAIT | wc -l
# 解决方案:
# - 开启 tcp_tw_reuse
# - 调整 tcp_max_tw_buckets
# - 缩短 TIME_WAIT 超时时间
总结
理解 Linux Load Average 的关键是:它不是 CPU 使用率,而是系统中 ” 忙碌 ” 进程的数量。这个数量既包括正在使用 CPU 的进程,也包括在等待 IO 的进程。
Load Average 三个数字的含义:
-
1 分钟:快速反映当前负载变化 -
5 分钟:中期趋势 -
15 分钟:长期平稳状态
判断高 Load Average 的正确方式:
-
数值 < CPU 核心数:通常没问题 -
数值 > CPU 核心数 × 0.7:需要关注 -
数值 > CPU 核心数 × 2:严重问题
和 CPU 使用率的关系:
-
Load Average 高 + CPU 使用率低 + iowait 高 = IO 瓶颈 -
Load Average 高 + CPU 使用率高 + iowait 低 = CPU 瓶颈 -
Load Average 低 + CPU 使用率高 = CPU 可能有尖峰,但系统总体不繁忙
排查口诀:
Load 高,先分清,CPU 瓶颈还是 IO。top 看 CPU,iostat 看磁盘,vmstat 里找 iowait。D 状态进程是关键,内核栈里找答案。文件描述符查 IO,pidstat 找真凶。
记住:Load Average 是症状,不是原因。优化 Load Average 不是目的,找到并解决真正的瓶颈(CPU、IO、网络、内存)才是目的。






