ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

Linux系统负载排查指南:一文读懂load average与性能监控命令

Linux系统负载排查指南:一文读懂load average与性能监控命令 大半夜被报警电话叫起来登录服务器之后我习惯性地先敲了三条命令uptime、top、free -h。屏幕上显示 load average 23.5新来的同事探过头问了一句“这个数值算高吗”当时我愣了一下这个问题其实没有标准答案但它背后藏着 Linux 性能排查最核心的一个认知系统负载不等于 CPU 使用率而对负载的理解深度直接决定你能不能快速定位到瓶颈。这篇文章想把我在日常运维和面试中反复用到的那套“负载排查 性能监控”命令体系完整梳理一遍。不管你是刚接触 Linux 的初学者还是已经在生产环境摸爬滚打的运维工程师只要你想搞清楚系统卡顿到底卡在哪、负载升高到底是 CPU 的锅、磁盘的锅还是内存的锅这篇文章都适合你。我会从最基础的概念讲起逐步拆解uptime、top、vmstat、sar、iostat、pidstat这些命令的核心参数和实战场景最后再分享几个我踩过的坑和排查思路。坦白说这些命令本身不难难的是知道在什么场景下用哪一条、看到输出之后怎么判断有没有问题。1. 负载到底是什么先搞懂 avg1/5/15 再谈监控1.1 系统负载不等于 CPU 使用率很多人一看到 load average 高第一反应就是“CPU 爆了”。但实际上Linux 内核里 load average 统计的是处于 TASK_RUNNING运行态正在使用 CPU 或者等待 CPU 调度和 TASK_UNINTERRUPTIBLE不可中断睡眠态通常是等待磁盘 IO、等待锁、等待 NFS 之类的内核态操作状态的进程数量之和然后取 1、5、15 分钟的平均值。为什么把不可中断睡眠态的进程也算进去这里有个很实际的原因如果进程卡在磁盘 IO 上CPU 虽然闲着等它但整个系统对外表现就是“卡住不动”你按uptime看到的负载照样飙升。我遇到过最典型的一次数据库服务器 CPU 使用率只有 5%但 load average 飙到 30 多最后定位到是底层存储阵列故障所有磁盘读写请求全部阻塞进程全部挂在 D 状态。所以你在排查高负载时心里一定要有这个弦负载高可能是 CPU 忙也可能是 IO 阻塞甚至两者叠加。明白了统计口径之后很多困惑就能解释通了。比如你用top看到 %Cpu(s) 的 us 只有 2%但是 load average 高得吓人这多半就是 D 状态进程在排队等 IO或者进程大部分时间在等待锁、等待内核资源。反过来如果 us 和 sy 都占满负载高才是正常的 CPU 繁忙表现。这两者的排查方向完全不同前者要查磁盘和存储后者要查应用代码和 CPU 密集任务。1.2 多核环境下的负载阈值判断那么回到开头那个问题load average 23.5 到底算不算高这个问题的标准答案取决于 CPU 核数。一个 32 核的机器load average 23.5 说明还有余量但如果你在一台 4 核的机器上看到这个数字那就意味着平均每个核心排着 6 个左右的任务在等 CPU用户体验必然下降。判断负载合理性的粗略标准是load average 长期小于 CPU 核数系统比较健康接近甚至超过核数说明 CPU 饱和或者有阻塞超过核数的 2 倍以上通常已经明显感受到卡顿。不过这里要提醒一下这个判断方式只适合 CPU 密集型场景遇到 IO 阻塞型的高负载光看核数是不够的必须结合后面的工具去确认瓶颈类型。还有一个老鸟容易忽略的细节只看 load average 还不够要看趋势。1 分钟、5 分钟、15 分钟三个数值的对比能告诉你负载是正在上升还是逐渐恢复。如果 load1 远大于 load15说明刚刚发生了突发负载系统正在忙碌如果 load1 和 load15 都高说明已经持续一段时间了属于长期过载如果 load1 快速下降说明你做的操作比如杀进程、扩容已经生效可以继续观察。2. 三板斧uptime、top、htop 的完整打开方式2.1 uptime一分钟看懂核心指标uptime是最快的负载查看命令没有之一。它的输出包含四段信息当前时间、系统已运行时长、当前登录用户数、load average 的三个值。运维习惯里登录服务器第一件事就是敲uptime因为它能让你在三秒内判断机器是否“有状况”。$ uptime 14:23:45 up 65 days, 3:22, 2 users, load average: 23.51, 18.23, 15.06这条命令还有一个隐藏用法就是配合 watch 做持续监听$ watch -n 2 uptime每两秒刷新一次方便你盯着负载的变化趋势。我一般会在以下场景用 uptime 做初步判断接到业务侧反馈系统慢、发布版本前确认服务器状态、压测过程中监控负载水位。它虽然简单但是高效是性能排查的起点而不是终点。想要看得更细就要上top了。2.2 top按 CPU 或内存排序找元凶top是 Linux 下最经典、最全面的实时性能监控工具。它的第一屏是系统概况包括 load average、进程总数、运行和休眠数量、CPU 使用率us 用户态、sy 内核态、ni 优先级调整、id 空闲、wa IO等待、hi 硬中断、si 软中断、st 被虚拟机偷走的时间以及内存KiB Mem和交换分区KiB Swap的使用情况。下面是动态刷新的进程列表。对于性能排查来说top 有几个必须玩熟的操作键按键作用使用场景P按 CPU 使用率排序找哪个进程在烧 CPUM按内存使用率排序找内存大户排查 OOM 隐患T按累计 CPU 时间排序看哪个进程长时间占用 CPU1展开/折叠每个 CPU 核心的使用率判断负载是否均衡有没有单核打满k输入 PID 后发送信号杀进程紧急情况下终止失控进程r调整进程的 nice 值临时降低某个进程的 CPU 优先级f进入字段管理界面增加/删除需要显示的列d修改刷新间隔默认 3 秒可以改成 1 秒我最常用的组合是一上来先按1看每个 CPU 核心的使用情况如果是单核满载而其他核都很闲通常说明程序是单线程设计或者存在热点锁然后按P和M分别找 CPU 和内存占用最高的进程。另外top 支持通过-p指定只监控某些进程$ top -p 1234,5678这个在排查某个具体服务进程时特别方便信息更清爽不会眼花缭乱。top 默认显示的进程树还不够直观想直接按父子关系管理进程就要用它的衍生品 htop或者原生的ps -ef --forest。2.3 htop交互式监控的进阶体验htop 不是 Linux 自带工具需要额外安装但它算得上是我日常工作里使用频率最高的性能监控工具。相比 tophtop 的优势主要有几点支持鼠标操作和彩色显示进程列表呈树形结构父子进程关系一目了然在顶部可以直观地看到 CPU、内存、Swap 的条形图可以直接在界面上搜索进程、发送信号不用记复杂的按键。我用 htop 最常见的场景是排查 Redis、Nginx 这类拥有多个 worker 进程的服务。树形视图能让你一眼看出 master 进程下挂了几个 worker每个 worker 分别吃了多少 CPU 和内存。如果某个 worker 的 CPU 使用率异常高可以在界面中直接选中它按F5查看它的线程视图再按F9给它发送信号或者直接杀掉。不过我要泼一盆冷水htop 虽然视觉友好但它展示的指标维度和 top 是差不多的别指望它能给你更多的数据深度。生产环境如果没装 htop靠 top 也一样能把问题定位清楚。工具只是习惯问题核心还是你对指标的理解。我的建议是平时自己学习用 htop 提升效率线上排查不要依赖它因为你不能保证每台机器都装了。3. 后台利器vmstat、sar、iostat、mpstat 逐个拆解3.1 vmstat 采样分析 CPU、内存和 IO当我们想把“症状”进一步收窄时vmstat是我第一个推荐的命令。它能同时报告进程状态、内存、分页、块 IO、CPU 使用率和上下文切换次数信息密度极高。$ vmstat 2 5 procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu----- r b swpd free buff cache si so bi bo in cs us sy id wa st 4 2 102436 33520 132572 6183136 0 0 186 245 16849 20028 12 8 68 12 0要特意说明执行参数vmstat 2 5表示每 2 秒采样一次一共采样 5 次。第一个 2 是间隔时间后面跟的是采样次数。重点看几列r运行队列中的进程数量也就是等待 CPU 的进程。这个值长期大于 CPU 核数时说明 CPU 饱和。b处于不可中断睡眠状态的进程数。b 列一直有值你要重点怀疑磁盘 IO 阻塞。si/soswap 换入换出量。如果长期不为 0说明内存严重不足系统在反复颠簸。si/so 变大是非常危险的信号。bi/bo块设备每秒接收/发送的块数量。bi 太大说明读磁盘频率高bo 太大说明写磁盘频繁。in/cs每秒中断数和上下文切换数。这两个值不是越低越好但如果异常飙高到几十万往往意味着系统出现锁竞争或者进程频繁切换可能要检查应用里有没有大量的线程 Busy loop。waCPU 等待 IO 完成的时间占比。这个值高说明 CPU 在空转等磁盘应用层的感受就是卡顿。vmstat 最好的使用方式是持续采样一段时间比如vmstat 1 30观察 30 秒。单看一次采样的数据意义不大要抓住趋势比如 cs 列是否在逐步攀升、wa 列是不是一直维持在 50% 以上。3.2 sar 定时采集看历史趋势vmstat 只能看当前时刻的情况想追溯过去一段时间系统发生了什么就得靠sar。sar 是 sysstat 包里的核心命令可以收集和报告 CPU、内存、IO、网络、进程创建、中断等几乎所有的系统性能数据。它最大的价值是能看历史趋势排查那些“现在看起来恢复了但某个时间段卡过”的问题。sar 的使用分为两个阶段数据采集和历史查看。第一阶段你需要在 cron 里配置 sysstat 的定时任务通常 sysstat 安装后会自动配置默认每 10 分钟采集一次数据保存在/var/log/sysstat目录下。第二阶段用 sar 的-f参数指定历史数据文件进行查看。常用命令清单# 查看 CPU 使用率今天的实时数据每 2 秒采样一次 $ sar -u 2 5 # 查看历史某天的 CPU 使用情况 $ sar -u -f /var/log/sysstat/sa$(date %d) # 查看内存和页面交换情况 $ sar -r # 查看系统负载平均值 $ sar -q # 查看网络设备流量 $ sar -n DEV 2 3 # 查看历史负载平均值 $ sar -q -f /var/log/sysstat/sa12我用 sar 最成功的一次排查经历研发反馈某个应用每天凌晨 3 点必卡顿。当时排查的时间已经过了凌晨现场看不到任何异常。我直接用sar -q -f /var/log/sysstat/sa15翻前一天的记录发现凌晨 2:50 开始 load average 从 2 飙升到 183:20 才回落。再配合sar -u发现 CPU us 也冲到 90% 以上最后顺藤摸瓜找到是定时任务里一个全量数据统计脚本没有做时间散列和业务高峰期撞在了一起。这种“事后复盘”的场景sar 是不可替代的。3.3 iostat 和 mpstat 分开衡量磁盘与 CPU 瓶颈iostat和mpstat同样来自 sysstat 包作用分别是看磁盘 IO 使用率和看每个 CPU 核心的使用率。它们把 vmstat 里的粗略指标细化到了具体设备上是定位“到底是哪块磁盘慢”和“到底哪个 CPU 核满了”的关键工具。iostat 我最常用的写法$ iostat -x 2 3-x代表扩展显示重点看几列%util设备带宽利用率。这个值接近 100% 说明磁盘已经接近饱和但这个指标对 SSD 和 RAID 卡来说并不完全准确因为 SSD 有非常强的并行处理能力%util 100% 时实际吞吐可能仍未打满要结合 await 一起看。awaitIO 请求的平均等待时间毫秒。机械盘一般应小于 10ms如果超过 100ms 说明磁盘响应已经很慢可能硬件故障或队列堆积。svctmIO 平均服务时间但这个值在新版 iostat 里已经意义不大可以直接忽略。rkB/s、wkB/s每秒读写的数据量。可以根据磁盘的标称吞吐能力判断是否达到上限。rrqm/s、wrqm/s合并后的读/写请求数。数值高说明 IO 调度合并效果好反而是正常现象。mpstat 的用法更直接$ mpstat -P ALL 2 3-P ALL显示所有 CPU 核心的使用率。如果某个核心的 %usr 或 %sys 长期比其他核心高很多程序大概率是单线程或者存在严重的锁竞争。我曾经在一个 Java 应用上遇到 CPU 16 个核只有一个 100%定位到最后是一个全局锁导致的串行化mpstat 一秒钟就暴露了问题不需要猜。4. 内存、磁盘、网络的专项排查4.1 内存排查free 输出的深度解读free -h是查看内存最直接的命令但很多人对这个命令的输出有误读。来看一个典型例子$ free -h total used free shared buff/cache available Mem: 31Gi 11Gi 1.2Gi 176Mi 18Gi 16Gi Swap: 31Gi 4.0Gi 27Gi初学者往往看到 used 11Gi、free 只有 1.2Gi 就以为内存不够用了。实际上buff/cache的那 18Gi 是 Linux 用来缓存磁盘数据的这是刻意为之的设计目的是加速文件读写。当应用需要内存时内核会自动回收 cache 分配给进程使用所以真正要关心的指标是available而不是free。available 表示在不触发 swap 的前提下还能分给进程多少内存。如果 Swap 的 used 一直在增长说明物理内存已经不够用系统正在把一部分进程的内存页搬到磁盘上这种状态会对性能造成显著影响。最有效的干预办法就是扩容物理内存或优化应用的内存使用。日常监控内存不应只盯 used 百分比更应关注 swap 的使用量和 available 的剩余情况。另外提一个实用小技巧在脚本里取内存可用度时优先用free -m | awk /Mem:/{print $7}拿 available 的数值不要用 free 那一列去判断。4.2 磁盘 IO 排查理解 iowait 的意义和局限前面说过CPU 使用率的 wa 字段代表 CPU 等待 IO 的时间很多人一看到 wa 高就断言“磁盘有问题”。这个结论在大多数机械盘场景下成立但对现代存储环境并不完全准确。NVMe SSD 和分布式存储的响应速度极快即使 IO 并发量很高CPU 的 wa 也不一定显著上升因为 CPU 可以快速处理完 IO 请求然后继续执行其他任务。所以我在排查 IO 压力时一般按照以下步骤走使用 iostat -x 看每个磁盘的 await、%util、rkB/s、wkB/s先确定是读多还是写多。使用pidstat -d 2按进程维度看 IO 读写情况确定是哪个进程在产生大量 IO。如果是读多再去查是不是有进程在频繁读大量小文件如果是写多关注是不是有日志写入、数据库日志持久化、或者大批量数据导出任务。如果 await 高但 %util 不高可能有 IO 队列堆积的隐患要深入查看后面是否有阻塞在 D 状态的进程vmstat b 列。这个组合判断比单看 wa 要可靠得多。4.3 网络排查从并发连接到流量监控网络层面的性能监控也经常被忽略尤其在高并发场景下连接数打满、网卡软中断抢占 CPU 都会让整个系统表现异常。常用的网络排查命令有下面几条# 查看网卡收发流量、错误包、丢包情况 $ sar -n DEV 2 3 # 查看当前 TCP 连接状态和数量 $ ss -s # 查看每个 IP 的 TCP 连接数 $ ss -ant | awk {print $5} | cut -d: -f1 | sort | uniq -c | sort -nr | head # 查看端口占用的进程 $ ss -lntp # 查看实时带宽占用需要安装 iftop $ iftop -i eth0我在排查一次 Web 服务响应变慢时用sar -n DEV发现网卡流量峰值远超带宽上限再配合ss -ant看到大量 TIME_WAIT 状态的连接没有及时回收导致新连接排队。调整内核参数 net.ipv4.tcp_tw_reuse、net.ipv4.tcp_fin_timeout 之后问题明显缓解。网络问题通常都是多指标联动的流量、连接数、重传率、CPU 软中断这几个都要一起看单看任何一项都容易误判。5. 从指标到进程精确定位罪魁祸首5.1 pidstat 按进程维度统计性能系统级指标定位了大致方向之后接下来的问题就是“谁导致的”。pidstat是 sysstat 包中专门按进程维度输出统计信息的工具它能告诉你每个进程具体占用多少 CPU、内存、IO甚至包括进程的上下文切换次数。# 查看每个进程的 CPU 使用率每 2 秒刷新一次 $ pidstat -u 2 5 # 查看每个进程的内存使用 $ pidstat -r 2 3 # 查看每个进程的磁盘 IO 读写 $ pidstat -d 2 3 # 查看每个进程的线程级统计 $ pidstat -t -p 12345 1pidstat 的输出会包含进程 PID、%usr、%system、%guest、%CPU 等字段查看磁盘 IO 时需要关注 kB_rd/s 和 kB_wr/s 这两列。有一次排查数据库备份导致的卡顿我用pidstat -d 2看到某个 mysqldump 进程的 kB_wr/s 持续在 60 万以上直接把它调了优先级问题立刻缓解。pidstat 还有一个好处是可以指定 PID 定向观察某个进程它的-p参数非常直观。5.2 ps 的隐藏用法与排序技巧每个人都用过ps -ef但在性能排查场景下这套默认输出并不方便。我更常用的是以下两种组合# 按 CPU 使用率从高到低排序显示前 10 个进程 $ ps aux --sort-%cpu | head -11 # 按内存使用率从高到低排序显示前 10 个进程 $ ps aux --sort-%mem | head -11 # 显示 CPU 使用率排前 5 的完整命令 $ ps -eo pid,ppid,cmd,%cpu,%mem --sort-%cpu | head -6 # 查看指定用户的全部进程比如 www 用户 $ ps -u www -o pid,cmd,%cpu,%mem--sort参数支持字段名前面加-表示降序加表示升序。这里的%cpu和%mem计算口径和 top 不同它是进程自启动以来的平均 CPU 使用率而不是瞬时值。所以 ps 更适合快速找“常驻内存大户”或“长期占用 CPU 的进程”如果要看瞬时爆发还是要用 top 或 pidstat。5.3 lsof 和 strace 定位异常进程的细节如果已经锁定了一个异常进程还想深入看它到底在做什么lsof和strace是两个硬核工具适合稍微进阶一点的场景。lsof用来查看进程打开的文件、目录、网络连接等。比如你想知道某个进程写入了哪个日志文件$ lsof -p 12345 | grep regular看这个进程正在监听哪些端口$ lsof -i -P -n | grep 12345strace则能追踪进程的系统调用和信号信息量大但也很耗时生产环境慎用。限于篇幅这里不详细展开但你要记得当所有常规手段都找不到进程诡异原因时strace 往往能一锤定音比如进程卡在某个 read 系统调用上不返回几乎可以断定是 IO 阻塞。6. 面试常问与实测排障存下来的几个坑6.1 面试中关于 load average 的常见提问因为经常面人我发现几个关于负载的考题特别容易踩坑这里顺手列出来问load average 高是不是一定代表 CPU 繁忙 答不是D 状态进程等 IO 也会推高 load average。问如何判断当前负载是否过高 答结合 CPU 核数判断运行队列长度同时看 vmstat 的 r 和 b 列还要排除 IO 阻塞场景。问top 中 wa 高和 load 高分别意味着什么 答wa 高说明 CPU 在等待 IOload 高可能由 CPU 饱和或 IO 阻塞引起两者需要结合 r、b 列和 iostat 输出综合判断。问如何快速定位哪个进程导致负载高 答top 按 P 排序看 CPU 占用pidstat -d 看 IO 占用lsof 看异常行为必要时 strace 跟踪系统调用。面试官真正想考察的不是命令背得熟不熟而是你有没有建立“从系统指标逆推到问题根因”的思维链。6.2 一次 load 飙高但 CPU 低的排障实录最后分享一次印象深刻的实战经历。某天业务反馈文件上传功能极慢登录服务器执行 uptimeload average 已经飙到 45但我的第一反应不是杀进程而是先跑 vmstat 1 5。输出中 b 列稳定在 4 左右wa 只有 8%这说明有进程长时间处于 D 状态但 CPU 本身并没有被 IO 等待拖垮太多。接着用 iostat -x 1 查看发现某块数据盘的 await 高达 700ms%util 接近 100%基本确定磁盘硬件或存储链路出了问题。通过 pidstat -d 1 找到产生 IO 最大的进程发现是一个临时文件的解压任务它正好写在这块故障盘上。我立刻联系存储团队确认最后确认为磁盘坏道导致读重试。整个过程耗时不到十分钟核心思路就是一个“判断瓶颈类型、定位磁盘、定位进程”的链路。如果一上来就盲目 kill 进程反而会掩盖真正的硬件故障。6.3 监控命令最佳实践清单结合我多年的运维习惯整理了一份基础监控命令速查表适合贴在笔记本里随时翻看排查目标第一命令第二命令确认方法整体判断是否需要介入uptimetopload 趋势 CPU/内存/wa 概览CPU 饱和vmstat r 列mpstat -P ALL运行队列长、某核高或整体高IO 阻塞vmstat b 列iostat -xD 状态进程、await 高、svctm 异常内存不足free -hsar -ravailable 低、si/so 持续增长定位进程top 排序pidstat -d/p具体 PID 的 CPU、内存、IO 占用网络异常sar -n DEVss -s流量打满、连接数积压、重传率高我之前还专门写过一个脚本每 5 分钟把 uptime、free、iostat、sar 的关键指标追加到日志文件里。这样在没有部署监控系统的情况下也能保留一份事后排查可追溯的数据来源。如果你刚接触这些命令建议在测试环境多跑几遍结合人工压测观察负载变化用过几次之后你对这些指标的体感会完全不一样。
RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进