问题背景
服务器突然变慢、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 1032 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//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 - 1032 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| wc -l # 2. 查看该进程的子进程 pstree -p # 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//io # rchar: 读的总字节数 # wchar: 写的总字节数 # syscr: 读系统调用次数 # syscw: 写系统调用次数 # read_bytes: 实际从磁盘读的字节数 # write_bytes: 实际写到磁盘的字节数
常见 IO 瓶颈场景:
场景一:大量日志写入
# 查看谁在写磁盘 sudo iotop -oa | head -50 # 发现某个 Python 进程在持续写日志,写入速度 50MB/s # 查看该进程的打开文件 ls -la /proc//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//stack
# 这个文件显示进程当前的内核堆栈,可以知道进程在等什么
# 查看 D 状态进程等待的 IO 设备
cat /proc//fd/* 2>/dev/null | head -20
# 或者查看进程打开的文件描述符
ls -la /proc//fd
# 如果某个文件描述符指向 /dev/sda1,说明在等磁盘 IO
第五步:不同场景的 Load Average 分析
5.1 场景一:Load Average 瞬间飙升
# 问题:早上 10:00 突然告警 Load Average 从 2 飙升到 20,5 分钟后恢复 # 1. 查看具体是哪个时间点 uptime # 10 Load Average 20.5, 12.3, 6.0 # 10 Load Average 8.2, 10.5, 6.5 # 2. 查看 1005 期间运行了什么进程 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# 查看进程树,看是否有大量子进程 # 如果是 java 进程 jstack # 查看 Java 进程的线程堆栈 # 如果是 nginx/php-fpm ps -eLf | grep | 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 # 临时修改(重启失效): echonone | 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、网络、内存)才是目的。
-
负载
+关注
关注
2文章
677浏览量
36731 -
cpu
+关注
关注
68文章
11343浏览量
226048 -
Linux
+关注
关注
88文章
11829浏览量
219637
原文标题:一文搞懂 Linux 系统负载 Load Average 到底怎么看
文章出处:【微信号:magedu-Linux,微信公众号:马哥Linux运维】欢迎添加关注!文章转载请注明出处。
发布评论请先 登录
最慢Linux 计算机启动需要4小时!
Linux CPU负载率的计算方式
基于嵌入式Linux网络计算机的操作系统的实现方法浅析
Linux系统负载Load Average的计算机制
评论