如何判断当前系统是 CPU 受限还是 IO 受限,给出三步定位法

解读

国内面试官问这道题,核心想验证三件事:

  1. 会不会用“最低成本”把瓶颈范围缩到 CPU 或 IO,而不是一上来就全链路压测;
  2. 是否熟悉 Linux 原生工具链(sar/iostat/vmstat/mpstat),因为大多数线上环境禁装额外 Agent;
  3. 能不能把指标翻译成业务语言,给出“下一步该谁改”的行动建议。
    回答时务必体现“三步闭环”:采样→量化→验证,且每一步都能落地到命令行,避免只背理论。

知识点

  1. CPU 受限典型指标:
    • 平均 CPU 利用率 > 80% 且 run queue(r 列)持续大于 CPU 核数;
    • 用户态 + 系统态占比之和 > 90%,idle 持续 < 10%;
    • 上下文切换(cs)与中断(in)增幅远低于 CPU 利用率增幅。
  2. IO 受限典型指标:
    • %util(iostat)> 70% 或 aqu-sz > 核数;
    • await 显著高于 svctm(差值 > 10 ms 即阻塞);
    • 内存无换页但 bi/bo(vmstat)高,且 CPU 大部分时间在 iowait。
  3. 快速区分技巧:
    • 把 CPU 拉到 100% 仍不能提高 TPS→CPU 不是瓶颈;
    • 把磁盘换 SSD 或 cache 预热后 TPS 翻倍→IO 是瓶颈。

答案

三步定位法(全部在压测峰值窗口 30 秒内完成,无需 root 权限):

第一步:秒级采样,先拍“全身照”
命令:sar -u -d 1 10 | tee snap.log
解读:

  • 若 “%idle” 持续 < 10 且 “%iowait” < 5,基本排除 IO,进入 CPU 分支;
  • 若 “%iowait” > 20 且磁盘 “%util” > 70,初步判定 IO 瓶颈;
  • 若两者都不明显,继续第二步。

第二步:定向放大,看谁在等
命令:iostat -xmt 1 5
指标:

  • await 与 svctm 差值 > 10 ms 或 aqu-sz > CPU 核数 → IO 受限;
  • 否则切到 mpstat -P ALL 1 5,观察每核 %usr+%sys 是否 > 90 且软中断均衡 → CPU 受限。

第三步:验证假设,快速松绑
CPU 验证:用 taskset 把进程绑到一半核,TPS 掉比例 < 20% → 确认 CPU 瓶颈;
IO 验证:把热点数据挂载到 tmpfs 或增大 buffer pool 让磁盘 util 降到 30% 以下,TPS 提升 > 30% → 确认 IO 瓶颈。
给出结论模板:
“当前 4C8G 节点在 2 k 并发下,CPU 利用率 95% 且 iowait 2%,run queue 6,属于 CPU 受限,建议优先优化算法复杂度或扩容计算节点。”

拓展思考

  1. 混合瓶颈:CPU 与 IO 同时踩红线时,国内惯例“先 IO 后 CPU”,因为 IO 优化(索引、缓存、批提交)往往零代码发布,风险更低。
  2. 云环境干扰:若宿主机超卖,steal 值高会被误判成 CPU 瓶颈,需用 cloud-monitor 看同一宿主机其他租户指标再做定论。
  3. 微服务链路:单节点定位完后,要用 tracer 把 CPU/IO 热点映射到跨服务 span,避免“本地 CPU 打满其实是因为下游 RT 高导致线程堆积”的假阳性。