Skip to content

性能四件套:vmstat / iostat / sar / pidstat ​

top 只能告诉你"谁吃 CPU"。判断瓶颈在 CPU、内存、磁盘还是网络,靠这四个工具联读。

场景 ​

"服务器很慢"是无效描述。要变成"CPU 打满"、"磁盘 IO 等待高"、"内存不足在换页"或"网络丢包",才能动手。

一、起手式 ​

bash
uptime
vmstat 1 5
iostat -xz 1 3
free -h
ss -s
text
 22:30:11 up 1 day,  4:10,  2 users,  load average: 8.41, 7.88, 7.62

load 8.41 在 4 核机器上是 2 倍过载。接下来看是什么导致的。

二、vmstat:一眼看四类资源 ​

bash
vmstat 1 5
text
procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu-----
 r  b   swpd   free   buff  cache   si   so    bi    bo   in   cs us sy id wa st
 6  2      0 184320  12800 512000    0    0   120  2048 12000 18000 38  6 50  6  0
 5  2      0 180112  12800 508800    0    0   240  4096 13200 19100 41  7 46  6  0

字段分组记忆:

列含义异常判断
r等待运行的任务数持续 > 核数 = CPU 排队
b不可中断睡眠(等 IO)持续 > 0 = IO 或锁
swpd已用 swap> 0 且持续增长要警惕
free空闲内存(不含缓存)小是正常的
buff/cache内核缓冲/页缓存大是好事
si / so每秒换入/换出非 0 就是内存不足
bi / bo每秒块读/写与磁盘能力对比
in / cs中断/上下文切换cs 极高 = 线程争抢或频繁切换
us / sy用户/系统态sy 高 = 系统调用多
id空闲—
wa等 IO> 20% 磁盘瓶颈
st被虚拟化偷走云主机超卖

free 显示内存少不等于有问题

Linux 会尽量用内存做页缓存(buff/cache)。真正的可用内存是 available:

bash
free -h
text
               total        used        free      shared  buff/cache   available
Mem:            15Gi        13Gi       512Mi       1.0Gi       1.8Gi       900Mi

available 才会在需要时被回收给应用。free 小是正常设计。

联读判断 ​

组合结论
r 高、us 高、id 低CPU 不够(计算密集)
r 高、id 高、wa 高IO 等待,CPU 在空转
b > 0、wa 高磁盘或 NFS 卡
si/so > 0内存不足,在 swap
cs 极高、sy 高上下文切换/系统调用过多
st > 5云主机被超卖,或宿主机争抢

三、iostat:哪块盘慢 ​

bash
iostat -xz 1 3
text
Device            r/s     rkB/s     w/s     wkB/s  rrqm/s  wrqm/s  r_await  w_await  aqu-sz  %util
vda              2.10     48.0  184.40  14721.6    0.00   12.40     0.82     8.42    1.24   98.40
vdb              0.00      0.0    0.20      1.6    0.00    0.00     0.20     0.42    0.00    0.12
字段含义判断
r/s / w/s每秒读写次数(IOPS)与盘的能力对比
rkB/s / wkB/s吞吐—
r_await / w_await平均等待时间(ms)SSD < 1ms,HDD < 10ms
aqu-sz平均队列长度持续 > 2 说明排队
%util设备忙碌百分比> 80% 饱和

-x 显示扩展指标,-z 隐藏空闲设备。只看 %util 不够:机械盘 %util 100% 是饱和,但 NVMe 队列深时 %util 也能到 100% 而吞吐还很高。要结合 await 和 aqu-sz。

bash
iostat -x 1 3 vda       # 只看某块盘
iostat -d -m 1 3        # 按 MB 显示

四、sar:历史趋势 ​

iostat/vmstat 只有当下。要复盘"昨天 3 点为什么慢",用 sar(需要 sysstat 服务在采集)。

bash
# CPU
sar -u 1 3
sar -u -f /var/log/sa/sa27 -s 03:00:00 -e 04:00:00

# 磁盘
sar -d 1 3

# 网络
sar -n DEV 1 3
sar -n EDEV 1 3        # 错误和丢包

# 内存
sar -r 1 3

# 队列与负载
sar -q 1 3
text
22:30:00     LINUX RESTART
22:31:01        CPU     %user     %nice   %system   %iowait    %steal     %idle
22:32:01        all     38.21      0.00      6.12      5.04      0.00     50.63

22:32:01     IFACE   rxpck/s   txpck/s    rxkB/s    txkB/s   rxcmp/s   txcmp/s  rxmcst/s
22:32:01      eth0  12401.2   11892.4   1842.11   2104.88      0.00      0.00      0.00

sar 的价值在于时间维度:%iowait 每天 3 点飙到 30%,就能对上备份任务。

bash
ls /var/log/sa/
text
sa25  sa26  sa27  sar25  sar26  sar27

sa* 是二进制,sar -f 读取;sar* 是文本报告。

五、pidstat:按进程拆 ​

iostat 说的是"盘忙",pidstat 说的是"谁在忙"。

bash
pidstat 1 3
pidstat -d 1 3
pidstat -r 1 3
pidstat -w 1 3
pidstat -u -p 28441 1 3
text
Average:      UID       PID    %usr %system  %guest   %wait    %CPU   CPU  Command
Average:       99     28441   38.21    2.10    0.00    0.12   40.31     2  java
Average:       27     29112    6.42    1.88    0.00    0.04    8.30     1  mysqld

Average:      UID       PID   kB_rd/s   kB_wr/s kB_ccwr/s iodelay  Command
Average:       99     28441      0.00  12288.00      0.00      42  java

Average:      UID       PID  minflt/s  majflt/s     VSZ     RSS   %MEM  Command
Average:       99     28441      0.00      0.00 4214320 2012340  12.40  java

Average:      UID       PID   cswch/s nvcswch/s  Command
Average:       99     28441   1842.10      42.10  java
模式看什么
默认%usr / %system / %wait
-d读写 KB/s 和 iodelay(IO 阻塞时间)
-rminflt(缺页)、majflt(从磁盘换页,非 0 说明内存不足)
-w自愿/非自愿上下文切换(锁竞争时非自愿切换高)

%wait 是进程等 CPU 的时间。%CPU 不高但 %wait 高,说明 CPU 被别的进程占了。

六、完整判断流程 ​

text
1. uptime 看 load 与核数
      ↓ load 高
2. vmstat 看 r / b / si / wa
      ↓
   ├─ r 高、us 高  → CPU 瓶颈 → pidstat 找进程 → top -Hp 找线程
   ├─ wa 高、b > 0 → IO 瓶颈  → iostat 找盘 → pidstat -d 找进程
   ├─ si/so > 0    → 内存不足 → free -h、pidstat -r、dmesg OOM
   └─ cs 高、sy 高 → 系统调用/切换过多 → pidstat -w、strace -c
      ↓ 以上都正常
3. sar -n DEV 看网络,sar -n EDEV 看丢包

七、一次完整案例 ​

现象:接口 P99 从 50ms 涨到 800ms。

bash
uptime
text
 22:40:11 up 1 day, 4:20,  load average: 9.12, 8.44, 7.90

4 核机器 load 9,过载。

bash
vmstat 1 3
text
 r  b   swpd   free   buff  cache   si   so    bi    bo   in   cs us sy id wa st
 2  6      0 120320  12800 512000    0    0   480  8192 14200 21000 12  4 22 62  0

b=6、wa=62%、id=22% → IO 瓶颈,CPU 在等盘。

bash
iostat -xz 1 2
text
Device  r/s    rkB/s   w/s     wkB/s  r_await w_await aqu-sz %util
vda    12.40  1024.0  420.2  18432.0   18.42   42.10   8.24  99.8

vda 的 w_await 42ms(SSD 应 < 2ms)、aqu-sz 8.24、%util 99.8% → 这块盘被打满了。

bash
pidstat -d 1 2
text
UID   PID   kB_rd/s   kB_wr/s iodelay  Command
 99 28441      0.00  16384.00      82  java

java 每秒写 16MB,iodelay 82 → 就是它。

结论:某个功能在疯狂写磁盘。继续查应用日志/慢查询,而不是去调 JVM 参数。

八、踩过的坑 ​

现象根因处置
vmstat 的 free 很小就以为内存不足页缓存占着看 available 和 si/so
wa 高但 iostat 看不出哪个盘没加 -x,或看漏了挂载点iostat -xz,结合 df 定位盘
load 高但 CPU 空闲b 列 / D 状态进程ps -eo stat,wchan
sar 没数据sysstat 服务没启用systemctl enable --now sysstat
%util 100% 但很快NVMe 队列深度特性看 await 和吞吐,不只看 %util
cs 极高线程数过多、锁竞争pidstat -w,查线程池配置
st > 10云主机争抢换规格或提工单
指标都正常但业务慢网络、下游、GC、连接池继续查 sar -n、应用侧监控