Linux 服务器 CPU / 内存 / IO 如何排查瓶颈
服务器突然变慢、响应卡顿、甚至出现超时告警,这些场景几乎每个做过线上服务的同学都遇到过。很多时候,根源就藏在 CPU、内存 或 磁盘IO 这三大资源瓶颈里。今天这篇文章就来系统聊聊:在Linux服务器上,如何一步步排查这三个维度的性能瓶颈,哪些指标最关键,用什么工具最有效,以及常见的误区和优化思路。
一、排查前的整体思路:USE 方法 + 分层诊断
在正式动手之前,先说一个排查心法:USE 方法(Utilization 利用率、Saturation 饱和度、Errors 错误数),这是Brendan Gregg 大神提出的黄金诊断框架。简单来说:
- Utilization:资源被用了多少?(太高 → 可能瓶颈)
- Saturation:资源队列有多长?(队列积压 → 肯定有瓶颈)
- Errors:有没有出错?(错误频发 → 硬件或配置问题)
排查顺序推荐:先整体概览 → 再逐资源深挖 → 最后定位到具体进程/代码。
常用“一分钟概览”命令组合(强烈建议做成alias或脚本):
uptime # load average 快速看整体压力
top # 或 htop,看 CPU/内存/进程
free -h # 内存使用
vmstat 1 5 # CPU、内存换页、IO 概览
iostat -xdz 1 5 # 磁盘IO 详细(-x 扩展统计、-d 只看磁盘、-z 忽略0活动设备)
sar -u 1 5 # CPU(需 sysstat 包)如果 load average 远高于 CPU 核数,且 wa(iowait)很高,先怀疑 IO;如果 us+sy 很高且 id 很低,先看 CPU;如果 swap 使用量飙升或 si/so 不为0,先查内存。
下面按 CPU → 内存 → IO 的顺序详细拆解。
二、CPU 瓶颈排查
2.1 关键指标判断 CPU 是否是瓶颈
- us(user) + sy(system) 持续 > 80-90%,id(idle) 接近0 → CPU 饱和
- wa(iowait) 持续 > 20-30% → 不是 CPU 忙,而是等 IO(本质是 IO 瓶颈)
- load average 远高于核数(例如 16 核机器 load 常年 40+)且 CPU 使用率不高 → 大量进程在等待(通常是 IO 或锁)
- 单核跑满(mpstat 看到某核 100%,其他低) → 单线程瓶颈或中断不均衡
2.2 常用工具及用法
top / htop(最常用入门工具)
Bashtop -c # 显示完整命令行,按 1 查看每核使用率 htop # F5 树形查看进程树,F6 按 CPU 排序看 %CPU 列,找到占用最高的进程。
mpstat(每核详细)
Bashmpstat -P ALL 1 5 # 每秒刷新5次,看哪颗核饱和pidstat(进程级 CPU)
Bashpidstat -w -u 1 # -u CPU,-w 上下文切换perf(火焰图级深度分析,推荐生产神器)
Bashperf top # 实时看占用 CPU 的函数 perf record -p <PID> -g -- sleep 10 perf report # 生成调用栈常用于定位 Java/Python/Node 等热点函数、锁竞争、系统调用过多等。
2.3 常见 CPU 瓶颈场景及处理
- 用户态 us 过高 → 业务代码死循环、复杂计算、正则、加密解密 → 用 perf 找热点函数优化
- 系统态 sy 过高 → 频繁系统调用(select/poll/epoll 问题、大量小文件读写) → 优化 IO 模型或批量处理
- 上下文切换 cs 极高(> 10000/s) → 线程过多 → 减线程、用协程
- iowait wa 高 → 别优化 CPU,先看下面 IO 章节
三、内存瓶颈排查
3.1 关键指标判断内存是否瓶颈
- free -h 中 available < 10% 物理内存,且 swap 已使用 → 内存压力大
- vmstat 的 si/so(swap in/out)不为 0 且持续 → 严重内存不足,正在疯狂换页
- sar -r %memused 持续接近 100%,且 %commit 超 100% → overcommit 风险
- slabtop 看到 dentry/inode 等缓存占用极高 → 文件系统元数据压力
3.2 常用工具及用法
free -h(快速看)
重点关注 available(真正可用的内存),而不是 free 列(被缓存占用了也算可用)。
vmstat 1 5
关注 free(剩余物理内存)、si/so(换页速率)、swpd(swap 使用量)
top / htop → 看 RES(驻留内存)、VIRT(虚拟内存)、SHR(共享)
smem 或 ps 查看进程真实内存占用(比 top 更准)
Bashps -eo pid,ppid,rss,vsz,cmd --sort=-rss | head -20 # 按 RSS 降序/proc/meminfo + slabtop
检查 Slab、SReclaimable 是否过大(文件缓存)。
3.3 常见内存瓶颈场景及处理
- 内存泄漏 → Java 进程 OldGC 频繁、Python 进程驻留暴涨 → 用 heap dump / malloc 分析
- 缓存占用过多 → Linux 会尽量把空闲内存当 page cache 用,无需慌张;但如果 dirty pages 过多会导致写阻塞
- OOM Killer 被触发 → dmesg | grep -i ‘out of memory’ 查看谁被杀
- Swap 使用过多 → 调低 swappiness(echo 10 > /proc/sys/vm/swappiness),或加内存/优化程序
四、IO 瓶颈排查(磁盘 IO 最容易被忽略)
4.1 关键指标判断 IO 是否瓶颈
- iostat -x %util 持续 > 80-90% → 磁盘饱和
- await(平均等待时间) > 10-20ms(SSD)或 > 50ms(HDD) → 延迟高
- top wa(iowait) > 30% → 系统在等磁盘
- r/s + w/s(IOPS)接近磁盘极限 → 随机读写过多
- svctm(服务时间)高 → 队列饱和
4.2 常用工具及用法
iostat -xdz 1 5(最核心)
- %util:磁盘利用率(最重要)
- await:平均 IO 等待时间
- svctm:平均服务时间
- r/s w/s:读写次数
- rkB/s wkB/s:吞吐量
iotop(进程级 IO 神器,像 top 一样看谁在狂写磁盘)
Bashiotop -o # 只显示有 IO 的进程vmstat 的 bi/bo(块读/写)
sar -d 历史 IO
blktrace / btt(深度分析,生产慎用,会产生大量日志)
4.3 常见 IO 瓶颈场景及处理
- MySQL/Redis 大量随机写 → %util 高,await 高 → 加索引、优化查询、用 SSD、分库分表
- 日志狂写 → 日志级别调到 warn、异步写日志、日志切割
- 大量小文件读写 → 元数据压力大 → 用 xfs/ext4 优化、增大 inode 缓存
- 脏页回写阻塞 → vm.dirty_ratio / dirty_background_ratio 调小
- 多盘 RAID0/10 还是单盘 → 升级 NVMe SSD 或分布式存储
五、快速 checklist + 实战脚本建议
把下面几行做成脚本 check-bottleneck.sh,一键跑:
#!/bin/bash
echo "=== Load & CPU ==="; uptime; mpstat 1 3 | tail -n +4
echo "=== Memory ==="; free -h; vmstat 1 3 | tail -n +3
echo "=== Disk IO ==="; iostat -xdz 1 3
echo "=== Top processes ==="; top -b -n1 -o %CPU | head -20
echo "=== IO processes ==="; iotop -b -n1 -o | head -15结语
排查瓶颈的核心是“先定性、再定位、最后优化”。别一上来就调参数,先用 top/vmstat/iostat 确认到底是 CPU/内存/IO 中的哪一个(或多个)在作妖,再用 perf/iotop/strace 深挖具体进程和代码。
大多数线上问题,80% 都能通过上面这些免费工具在 10-30 分钟内定位到大概原因。剩下的 20% 才需要火焰图、eBPF、systemtap 等高级手段。