
那一周我印象特别深早上刚到工位群里就炸了——线上数据库响应时间翻了三倍用户后台一直转圈。我第一反应是登录服务器uptime看了一眼负载显示load average: 15.03, 12.66, 8.85机器是 8 核。说实话那个瞬间我脑子里闪过一堆猜测是不是慢SQL又冒出来了是不是连接数被打满是不是昨晚的备份脚本没结束结果top一按CPU 使用率才 30% 出头。这就很有意思了——负载高到离谱CPU 却在摸鱼。也就是从那次开始我才认真去深挖“Linux平均负载”这个基础指标背后的东西。很多资料上都写过定义但没有一个真正解释清楚为什么会出现“高负载低CPU”这种看起来自相矛盾的状态。这篇文章就把我对平均负载的全部理解写出来从定义到排查流程到避坑心得一次性讲透。不管你是刚接触 Linux 的运维新人还是被负载告警折腾过的后端开发都值得花十分钟把它看完。1. 平均负载是什么先弄清这个数字的真实含义1.1 官方定义与三个数字的解读逻辑load average在 Linux 里表示的是系统的平均负载官方定义是单位时间内系统处于可运行状态和不可中断状态的平均进程数。这里有三个值比如上面提到的15.03, 12.66, 8.85分别对应过去 1 分钟、5 分钟、15 分钟的平均值。这三个数字不是随机摆在那里的看它们能判断负载变化趋势如果 1 分钟值 5 分钟值 15 分钟值说明负载在快速上升系统正在变拥挤如果三个值基本持平说明负载相对稳定如果 1 分钟值 5 分钟值 15 分钟值说明负载在下降系统压力正在缓解。我记得第一次带新人排查问题的时候对方看着uptime输出问了一句“load 是 8.85这算高吗”我当时反问他“你这台机器几个核”他愣了半天说不知道。这就是新手最容易踩的坑——平均负载必须除以 CPU 核心数才有意义。举个具体例子8 核机器上负载是 8相当于平均每个核心刚好有一个任务在处理属于满载但不超载负载是 16说明每个核心上平均有两个任务在排队系统已经明显过载。换算过来负载值小于核数CPU 还有余量等于核数刚好满载大于核数任务开始堆积、排队响应时间就会变长。1.2 平均负载和 CPU 使用率的本质区别这是被问得最多的一个问题也是最容易混淆的一对概念。平均负载不等于 CPU 使用率两者反映的是不同层面的信息。CPU 使用率是单位时间内 CPU 处于忙碌状态的百分比它衡量的是 CPU 的“忙碌程度”。而平均负载衡量的是系统中处于“需要CPU处理”状态的进程数量。我习惯用一个生活化的类比来解释把 CPU 核心想象成高速公路的车道CPU 使用率是车道上车辆的行驶占比负载则是车道上的车加上匝道口排队等待进入的车。关键点来了不可中断状态D 状态的进程也会计入负载。什么是不可中断状态最常见的就是进程正在等待磁盘 IO 或者网络 IO 返回这期间进程无法被中断即使是 kill 命令也没法立刻终止它。这类进程并不占用 CPU 计算能力但它们阻塞在那里同样会被系统计入平均负载。所以会出现一个看似矛盾的现象负载很高但 CPU 使用率很低。这种情况往往不是 CPU 不够用而是磁盘 IO 太慢大量进程堵在 IO 等待上。我那次数据库事故的根因就是这个后面整整折腾了一天才把所有线索串起来。2. 平均负载高一定是CPU问题吗三种典型场景拆解2.1 CPU密集型计算过载的直白剧本先看最简单、也最容易理解的场景——CPU 密集型负载。这类任务的特点是进程在绝大多数时间里占用 CPU 进行运算比如视频编解码、数据压缩、科学计算、复杂的脚本处理任务等等。特征非常明显负载上升的同时CPU 使用率也跟着飙升。拿一台 4 核的云主机举例如果有一个纯 Python 脚本在跑无限循环做数值计算那这个进程能把一个核占满top里%CPU一栏能看到长时间维持在 100%系统负载会稳定在 1 左右。如果有四个这样的进程负载就会冲到 4 附近CPU 使用率也会接近 100%。我之前帮客户排查过一台跑离线报表任务的服务器CPU 使用率持续在 90% 以上负载已经飙到核数的两倍用户提交报表请求后要等很久才能看到结果。这种情况的排查方向很直接找出消耗 CPU 的元凶进程看看能不能从代码层面优化或者把任务调度到非高峰期执行。如果业务量持续增长CPU 确实扛不住了再考虑扩容或迁移。2.2 IO密集型最容易被误判的隐藏杀手IO 密集型场景比 CPU 密集型要隐蔽得多也是我见过最多“误诊”的案例类型。前面提到进程在等待磁盘读写、网络传输等 IO 操作时会进入不可中断的 D 状态。这种进程不消耗 CPU 算力但同样计入平均负载。典型的表现就是load average 居高不下CPU 使用率却很平淡甚至只有百分之二三十。这时候如果你只盯着 CPU 看很容易得出“CPU 浪费了加核数”的错误结论。但实际上加多少核都没用瓶颈在磁盘。我印象很深的一个案例一套内网的文档管理系统每天的凌晨同步任务会把负载拉得很高用户抱怨系统卡顿。登上去看到 16 核机器负载到了 22CPU 却只用了 15%。我第一反应是磁盘出了问题跑iostat -x 1一看%util接近 100%await都快上 300 毫秒了——果然磁盘在拼命干活但跟不上吞吐。后来把同步任务做了限速并且错开业务高峰期负载立刻降下来了。怎么快速识别 IO 瓶颈有两个关键指标vmstat输出里的waiowait列数值较高top里进程状态出现大量D。一旦看到这两个信号就要把重点转移到磁盘或网络 IO 的排查上。2.3 进程调度竞争多核架构下的排队效应第三种场景是大量进程或线程在等待 CPU 调度。看似和 CPU 密集型很像但它们之间有微妙的差别CPU 密集型是少数几个任务在长时间霸占 CPU而调度竞争场景下任务的到达频率很高虽然单个任务不需要太多 CPU 时间但数量一多排队时间就成了瓶颈。一个很常见的原因就是线程池或者进程池的并发数设置得太高。Java 服务里如果核心线程数配置不合理比如一台 8 核机器上开了 200 个线程每个线程只需要完成很轻量的计算任务但因为线程太多CPU 光是在线程之间切换上下文就要耗掉不少资源。配合mpstat和pidstat -w能看到上下文切换次数cswch/s和nvcswch/s非常高。这种场景下靠加核数可能缓解一部分压力但更合理的方式是调优应用层的并发策略限制线程数量、优化锁的粒度、减少频繁创建销毁线程的写法。负载不是越高越需要提升硬件有时候把配置改正确问题自然就消失了。3. 排查平均负载飙高的完整实操流程3.1 第一步先用 uptime 和 top 把握全局状态不论收到监控告警还是用户反馈我登进服务器的第一件事永远是跑uptime。这个命令没有花里胡哨的参数输出里直接给出 1 分钟、5 分钟、15 分钟三个负载值。通过对比这三个值能迅速判断负载是在上升还是回落。如果 1 分钟负载远高于 15 分钟负载说明系统正处于突发的压力高峰这时候要赶紧查。如果三个值都很高且平稳说明系统已经持续超载一段时间了需要排查造成持续高负载的常驻任务。紧接着跑top注意看这几块内容第一行的load average和uptime一致第三行的%Cpu(s)行重点看us用户态、sy系统态、wa等待 IO三个值进程列表的%CPU、%MEM还有 STAT 列的D、R、S状态。这里有一个top使用的小技巧进入top后按P键可以按 CPU 使用率排序按M键按内存排序按x键可以高亮当前排序列。很多人看top只盯着上面几个进程但如果不排序真正消耗 CPU 的进程可能被淹没在列表中间。3.2 第二步用 mpstat 定位 CPU 核心级别的使用分布top显示的 CPU 使用率是整体汇总值但多核机器上每个核心的情况可能差异巨大。特别是当负载高且硬件中断密集时可能出现“一颗核心被打满其余核心闲置”的奇葩情况。这时候就需要mpstat出马。mpstat -P ALL 1 5这个命令表示每 1 秒采样一次连续采样 5 次把每个 CPU 核心的使用情况都列出来。输出里几列比较关键%usr用户态占用%sys内核态占用%iowaitCPU 等待 IO 的时间占比这个指标对判断 IO 瓶颈非常重要%irq%soft硬中断和软中断处理占用这块如果偏高可能是因为网卡流量过大或硬件故障导致中断风暴。如果发现所有核心的%usr都很高说明是计算密集型如果%iowait明显偏高那就要顺着 IO 的方向继续查如果只有个别核心特别忙碌、其他核心闲着那要检查是否有 IRQ 亲和性配置问题或者某些应用把线程绑在了特定 CPU 上。3.3 第三步用 pidstat 揪出消耗资源的元凶进程mpstat能看到整体分布但具体是哪个进程在捣鬼还得用pidstat。这个命令在 sysstat 包里装好之后可以按进程维度查看各种资源消耗情况。查 CPU 使用率pidstat -u 1 5查内存pidstat -r 1 5查 IO 读写pidstat -d 1 5查上下文切换pidstat -w 1 5实际定位时我会根据前面的线索选工具怀疑 CPU 瓶颈就看-u怀疑 IO 瓶颈就看-d。pidstat输出的第一列是进程 PID最后一列是命令名找到 PID 后可以进top或者/proc/PID/status进一步确认进程详情。举个例子某次排查发现负载高但 CPU 正常pidstat -d显示有个进程的wr_kB/s一直很大点开一看是个 Java 应用在疯狂刷日志。查了日志框架配置发现 error 级别日志被调成了 debug而且输出到磁盘上的 logger 没有做异步处理一下子就找到了问题根源。3.4 第四步用 vmstat 和 iostat 做交叉验证单独一个指标容易骗人但多个指标组合在一起很难同时撒谎。所以最后我会用vmstat和iostat交叉验证前面的判断。vmstat 1 10vmstat输出里关注这几列r运行队列中的进程数量如果持续大于 CPU 核数说明 CPU 非常繁忙b处于不可中断睡眠状态的进程数数值高说明 IO 阻塞严重si/soswap 换入换出如果持续非零内存可能不足系统在敲打磁盘交换us/sy/wa/st用户态、系统态、等待 IO、被虚拟机偷走的时间比例。iostat -x 1 3iostat的-x参数会输出扩展信息主要看%util磁盘忙碌的百分比awaitIO 请求的平均等待时间毫秒这个值越大体验越差svctm设备服务的平均时间r_await/w_await读和写的平均等待时间。如果你的%util在 90% 以上await也上百毫秒那不用犹豫了磁盘就是瓶颈。这里有个经验之谈看到负载高先不要慌也不要急着重启或者加机器把vmstat和iostat拉出来看几秒大概率能找到方向。我见过不少同行上来就重启服务结果负载暂时降下来过了几小时又弹回去——因为根因没解决重启只是治标不治本。4. 常见问题与排查技巧实录4.1 负载异常的典型场景速查表我在实际工作中整理过一个速查表每次碰到负载问题都按这个思路快速过一遍症状特征可能的根因优先排查的命令负载高 CPU 使用率高计算密集型任务线程池配置过大top、pidstat -u负载高 CPU 使用率低 wa 高磁盘 IO 瓶颈iostat -x、vmstat负载高 大量 D 状态进程磁盘或网络 IO 阻塞NFS 卡顿ps aux查看 STATstrace负载高 上下文切换频繁线程数过多锁竞争严重pidstat -w、vmstat的 cs 列负载波动明显1 分钟远高 15 分钟定时任务叠加流量突增crontab -l配合日志检查这张表不是万能药但它能帮你在头脑风暴阶段快速缩小范围。实际定位过程中我还会顺手做一件事翻一下监控面板里负载的趋势图。如果负载是阶梯式上升很可能和某个定时任务有关如果是平滑缓慢上升可能和持续增长的业务流量有关如果是脉冲式波动大概率是周期性任务或者流量突刺。4.2 面试官最爱问的几个平均负载问题因为“Linux平均负载”是基础中的基础很多面试官爱拿这个点来试候选人有没有真正的系统调优经验。我总结几个高频提问和对应的思考路径。第一问“一台 4 核机器上load average为 4意味着什么”很多人脱口而出“说明 CPU 已经满了”这个答案不能算全错但不严谨。更严谨的说法是“系统处于满载边缘平均每个核心有一个任务在执行或等待执行需要结合 CPU 使用率、IO 等待等指标进一步判断系统是否存在瓶颈”。第二问“负载高 CPU 使用率却很低为什么”回答的核心要落在那两类状态上——进程处于不可中断状态D 状态等待 IO特殊情况还包括等待锁、等待网卡队列等。这时候负载计算的是“阻塞进程数”而不是“忙碌的 CPU 数”。第三问“如何快速定位负载高的元凶”解题思路从整体到局部uptime看趋势mpstat -P ALL区分 CPU 还是 IOpidstat -u和pidstat -d定位进程最后vmstat和iostat做验证。如果能把排查链路完整、清晰地表达出来比死记硬背命令要加分。4.3 我踩过的几个真实深坑排查负载这几年我自己也踩过不少坑挑几个最典型的说说。第一个坑只盯 CPU忽略 IO。早期排查的时候看到负载高就一股脑找进程、杀进程折腾半天负载还是高。后来才意识到 IO 等待也会推高负载而 CPU 却闲着。这个教训在现代存储和监控系统越来越普遍的情况下尤其重要——SSD 的随机写性能远高于 HDD但本身也有寿命、队列深度的问题iostat不能不看。第二个坑用负载值直接跨机器比较。8 核机器负载 4 可能很健康2 核机器负载 4 已经超载了。负载值必须和机器核数挂钩。如果换了机器或者扩容了 CPU要重新评估负载的合理区间不能用老经验硬套。第三个坑忘了看 15 分钟负载的历史惯性。负载是一个平均值短期内即使任务结束15 分钟的平均值还会保持高位慢慢回落。如果只看 15 分钟值判断系统“仍然很忙”可能会做出错误决策比如继续加资源或者重复重启。正确做法是结合 1 分钟值和趋势图判断当前真实压力。第四个坑忽略软中断softirq带来的负载。网络密集型应用在高并发情况下软中断可能耗费大量 CPU而这些开销在top的汇总里常常被归到sy里。如果不加区分可能误判为业务代码问题实际上需要调整网卡队列RSS或者应用多队列配置。5. 性能优化里的几个实战经验补充5.1 合理设置监控阈值别等 15 分钟大数据才发现问题监控系统里给平均负载设置告警阈值时很多人直接写死一个数值比如“负载大于 5 告警”。这在混合规格的集群里很容易失效——小机器容易误报大机器可能漏报。更合理的做法是按核数比例设置阈值。比如设置负载达到 CPU 核数的 70% 时触发预警达到 100% 时触发告警达到 150% 以上触发紧急告警。同时配合负载的趋势变化比如 1 分钟负载持续 5 分钟高于核数才真正推送告警避免瞬时波动导致频繁打扰。另外告警里最好带上上下文信息——比如把这台机器的核数、CPU 使用率、iowait、最近的线程数变化一起放进来。收到告警的人不用再花五分钟登服务器看基础信息直接就能判断紧急程度和排查方向。5.2 当加 CPU 解决不了问题时从线程数和 IO 模型找突破“负载高就加CPU”是很多初入行的逻辑但加完之后发现效果不明显这通常说明方向错了。我曾经处理过一个 Java 网关服务8 核机器负载持续在 10 左右加了 8 核变成 16 核机器后负载还是 10 上下几乎没有改善。后来观察vmstatcs列每秒钟上下文切换高达 60 万次pidstat -w显示大量的非自愿上下文切换nvcswch/s。原因很快浮出水面——这个服务的核心线程池配置了 512 个线程大量线程在共享一把锁CPU 时间全部耗在排队和锁等待上。把线程数调整成和核数相近的水平优化锁的粒度之后负载立刻降到 3 以下。这种案例给我最大的启发是系统性能优化的核心不是只看资源指标而是要理解上层应用的并发模型和资源偏好。平均负载只是一个现象它告诉你“出事了”但不告诉你“为什么出事”。要回答“为什么”需要把操作系统的 CPU 调度、进程状态、中断处理、IO 栈知识都串起来。5.3 顺手把那些容易误读的细节记住uptime显示的负载值精度不用过分纠结关键是趋势。运维不是做科研不要为了小数点后面的精度浪费太多时间。top中进程的%CPU值可能是多核累加的结果。一个进程开 4 个线程跑满 4 个核top里显示可能是 400%而不是 100%。这不算异常但很多刚入行的人会被这个大数字吓到。load average是内核基于调度器统计出来的采样值存在一定的滞后性。即使某个进程已经结束负载值也会随时间逐步回落不会瞬间归零。明白这一点就不会在任务结束后对着下降缓慢的负载值干着急。用stress或stress-ng这类工具模拟负载做测试时注意控制参数不要直接在核心业务机上跑满负载压测很容易触发内核的软锁等问题。我的习惯是在压测机或者预发环境做实验毕竟生产环境的稳定性才是第一位的。附一套顺手好用的排查脚本最后分享一个我经常用的组合命令适合在拿到一台负载异常的机器后快速收集信息uptime echo --- vmstat --- vmstat 1 5 echo --- mpstat --- mpstat -P ALL 1 3 echo --- iostat --- iostat -x 1 3 echo --- top 10 CPU --- top -b -n 1 -o %CPU | head -40这一串命令会依次输出负载趋势、内存和运行队列、每个核的使用分布、磁盘 IO 明细、CPU 占用最高的进程列表。执行一次就能把定位问题所需的核心数据一次性拿到手不用反复登服务器敲命令。建议把sysstat包安装好这些命令基本都自带。我在实际使用中发现这套流程真正跑顺了之后一次负载排查从登录到定位根因基本上能控制在五分钟以内。关键在于不猜、不赌一路用数据说话先从宏观指标框定方向再到微观进程确认元凶最后优化调整验证效果。久而久之负载告警对我来说就不再是“狼来了”而是一道有标准解法流程的题目。