Linux 下 vmstat 命令显示 r 列长期大于 CPU 核数说明什么?

文章导读
vmstat 的 r 列长期大于 CPU 核数,说明就绪队列拥堵,但不一定是 CPU 算力不足,需结合 us/sy/wa/cs 等指标定位真实瓶颈后再决定扩容或优化。
📋 目录
  1. 命令速用版
  2. vmstat 列详解
  3. 为什么会这样
  4. 分步处理
  5. 真实案例复盘
  6. 怎么验证是否生效
  7. 常见坑
  8. 参考来源
A A

vmstat 的 r 列长期大于 CPU 核数,说明就绪队列拥堵,但不一定是 CPU 算力不足,需结合 us/sy/wa/cs 等指标定位真实瓶颈后再决定扩容或优化。

先说结论:r 值持续高于 CPU 核心数表示进程在排队等待调度,可能由 CPU 不足、I/O 阻塞、上下文切换过高或内存压力引起,需多维度排查而非直接加 CPU。

  • 先定位:用 vmstat 1 持续观察 r、us、sy、wa、cs、b 列的组合关系
  • 先做:根据指标组合选择 iostat、pidstat、ps 等工具深入排查
  • 再验证:优化后再次运行 vmstat 确认 r 值回落且业务响应改善

命令速用版

先获取 CPU 核心数作为对比基准:

nproc

持续观察 vmstat 关键指标(每秒采样,连续 10 次):

vmstat 1 10

重点关注 procs 列的 r 和 b,以及 cpu 列的 us、sy、id、wa。注意不同 Linux 发行版 vmstat 输出列数可能略有差异,请以表头为准:

  • r:运行和等待 CPU 的进程总数
  • b:处于不可中断睡眠的进程数
  • us:用户态 CPU 使用率
  • sy:内核态 CPU 使用率
  • wa:等待 I/O 的 CPU 时间百分比
  • id:空闲 CPU 百分比

若 r 高但 us+sy 不高,进一步检查上下文切换和 I/O(注意列号对应 cs 通常为第 12 列):

vmstat 1 5 | awk 'NR>2 {print $12}'  # 查看 cs 列,跳过 2 行表头
iostat -x 1 5  # 查看磁盘 await 和%util

vmstat 列详解

标准 procps-ng 版本 vmstat 输出列顺序如下,排查时请对照表头确认:

Linux 下 vmstat 命令显示 r 列长期大于 CPU 核数说明什么?
列号字段含义
1r运行队列长度(运行 + 等待 CPU)
2b不可中断睡眠进程数
3-6memoryswpd, free, buff, cache
7-8swapsi (入), so (出)
9-10iobi (读), bo (写)
11in中断次数
12cs上下文切换次数
13-17cpuus, sy, id, wa, st

注意:部分旧版 Unix 或特定发行版可能列序不同,务必先运行一次 vmstat 确认表头。

为什么会这样

r 列统计的是正在 CPU 上运行 + 等待 CPU 调度的进程总数。当这个值长期超过 CPU 核心数时,说明调度器排不上号,但这不等同于 CPU 算力被占满。

常见原因有四类:

  • CPU 真正不足:us+sy 合计持续高于 70%,r 高且 id 低,说明计算任务确实超过处理能力
  • I/O 阻塞导致就绪队列堆积:进程发起读写后进入睡眠,完成 I/O 后重新进入就绪队列,此时 r 高但 wa 也高,top 中看不到高 CPU 进程
  • 上下文切换风暴:cs 值异常高而 us/sy 未饱和,说明 CPU 大量时间花在调度上而非执行任务,常见于大量短连接服务或线程数配置过高的应用
  • 内存压力引发连锁反应:swap 有进出(si/so 非零)且 free 偏低,进程缺页时需从 swap 调入,期间进入睡眠等待 I/O,醒来后继续排队争 CPU

分步处理

步骤 1:确认 r 值是否真的长期偏高

瞬时峰值可能正常,需观察至少 1-2 分钟:

vmstat 1 60

若 r 值在 60 次采样中大部分时间超过 CPU 核数,才视为长期偏高。

步骤 2:根据指标组合判断瓶颈类型

Linux 下 vmstat 命令显示 r 列长期大于 CPU 核数说明什么?
指标组合可能原因下一步
r 高 + us/sy 高 + id 低CPU 算力不足用 top/pidstat 定位高 CPU 进程
r 高 + wa 高 + us/sy 低I/O 阻塞用 iostat 检查磁盘响应
r 高 + cs 异常高上下文切换过多用 pidstat -w 定位高切换进程
r 高 + si/so 非零 + free 低内存不足导致换页用 free -h 确认内存状态

步骤 3:针对性排查

若怀疑 I/O 阻塞,检查是否有 D 状态进程(排除表头干扰):

ps -eo stat,pid,comm | grep -v STAT | grep "^D"

若怀疑上下文切换,查看具体进程的切换次数:

pidstat -w 1 5

若怀疑内存压力,检查 swap 活动:

free -h
vmstat -s | grep page

步骤 4:优化措施

  • CPU 不足:考虑扩容 CPU 或优化计算密集型任务
  • I/O 阻塞:检查磁盘健康、优化查询、减少同步写操作
  • 上下文切换:限制线程池大小、改用 epoll 等高效模型、合并小请求
  • 内存压力:增加物理内存、优化缓存配置、排查内存泄漏

真实案例复盘

场景:某 Web 服务 r 值持续为 16(8 核 CPU),但 us+sy 仅 30%。

Linux 下 vmstat 命令显示 r 列长期大于 CPU 核数说明什么?

排查:

  1. vmstat 发现 wa 高达 40%,cs 正常。
  2. iostat 发现某磁盘 await 超过 100ms,%util 接近 100%。
  3. ps 发现多个进程处于 D 状态,等待磁盘 IO。

原因:应用日志同步写入磁盘过快,导致 IO 队列堵塞,进程完成 IO 后集中争抢 CPU,推高 r 值。

解决:改为异步日志写入,r 值回落至 4 左右,wa 降至 5% 以下。

怎么验证是否生效

优化后再次运行 vmstat,确认以下变化:

  • r 值回落至接近或低于 CPU 核心数
  • 对应瓶颈指标改善(如 wa 下降、cs 下降、si/so 归零)
  • 业务响应时间缩短(可用 curl -w 或应用日志验证)

示例验证命令:

vmstat 1 10
uptime  # 查看 load average 是否同步下降

若 r 值仍高但业务响应正常,可能是短生命周期进程导致,需用更细粒度工具确认:

pidstat -u 1 10

常见坑

  • 只看 top 会漏掉问题:top 默认刷新周期较粗(通常 3 秒),短生命周期或频繁阻塞的进程在 top 中%CPU 极低,但会持续推高 r 值
  • r 高不等于 CPU 忙:r 高但 id 也高是典型的"假性 CPU 空闲",大量进程卡在不可中断睡眠(D 状态),堆满运行队列却不消耗 CPU
  • 瞬时峰值无需干预:短暂 r 值超过核数可能正常,只有长期持续才需处理
  • 容器环境 r 值可能失真:在 Kubernetes Pod 或 cgroup 限制下,r 可能被 CPU quota 扭曲,此时 b 列(等待 I/O 的进程数)更值得盯
  • 不要盲目加 CPU:若瓶颈在 I/O 或内存,增加 CPU 核心数无法解决问题,反而浪费资源
  • 列号依赖风险:使用 awk 提取列时务必确认表头,不同版本 vmstat 列序可能变化

参考来源