一文搞懂 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 Averageload(t-1) 是上一个计算周期的 Load Averagen 是当前活跃进程数(Running + Uninterruptible Sleep)a 是衰减系数,设置为 exp(-5/60s) = 0.998
计算每 5 秒执行一次,但报告给用户空间是每 1 秒更新一次。
三个时间窗口的衰减系数:
1 分钟:a = exp(-5/60) = 0.99825 分钟:a = exp(-5/300) = 0.983515 分钟: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,而不是在计算。
# 查看 iowaittop -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很慢# 查看哪个进程在大量使用 IOiotop -oa# 或pidstat -d 1 5# 如果没有 iotop,用 ps 辅助判断ps aux | awk '$8 ~ /D/ {print $0}'
第四步:高 Load Average 的完整排查流程
4.1 第一步:确认 Load Average 是否真的过高
# 查看 CPU 核心数和当前 Load Averagenprocuptime# 如果 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,用 pidstatsudo 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 -mswapon -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 导致的# 查看磁盘 IOiostat -x 1 3
常见根因:
5.3 场景三:Load Average 和 CPU 使用率都很高
# 问题:Load Average 持续 15,CPU 使用率 90%# 诊断:top -bn1# 确认是哪个进程占用了 CPUps aux --sort=-%cpu | head -10# 找到 CPU 占用最高的进程# 查看该进程的详细信息pstree -p <pid># 查看进程树,看是否有大量子进程# 如果是 java 进程jstack <pid># 查看 Java 进程的线程堆栈# 如果是 nginx/php-fpmps -eLf | grep <pid> | wc -l# 查看 worker 进程数
常见根因:
第六步:监控和告警配置
6.1 基于 Load Average 配置监控告警
#!/bin/bash# save as: check_load.sh# 配置 cron: */5 * * * * /usr/local/bin/check_load.shTHRESHOLD=$(nproc)LOAD=$(awk '{print $1}' /proc/loadavg)LOAD_INT=${LOAD%.*}if [ "$LOAD_INT" -gt "$THRESHOLD" ]; thenecho"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:nodestatic_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 资源不足
告警规则:
# PrometheusRulegroups:-name:node-loadrules:-alert:NodeHighLoadexpr:node_load1/count(node_load1)>0.8for:5mlabels:severity:warningannotations:summary:"Node {{ $labels.instance }} load is high"description:"Load Average 1m = {{ $value }}, CPU cores = {{ $labels.cpu }}"-alert:NodeCriticalLoadexpr:node_load1/count(node_load1)>1.2for:2mlabels: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 IOfree -m# 如果 Swap 使用量持续 > 0,说明内存不足# 解决方案:增加内存或限制进程内存
7.3 网络 IO 瓶颈
# 如果 Load Average 高但磁盘 IO 不高,检查网络 IOsar -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 三个数字的含义:
判断高 Load Average 的正确方式:
和 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、网络、内存)才是目的。