CPU 正常、内存正常、负载 30+?——这次真不是 CPU 的锅

——上篇讲了 CPU,这篇讲它"最常甩锅"的兄弟:磁盘 IO(附银行 3 个真实案例)


阅读时长:约 6 分钟
适合谁:Linux 运维、系统管理员、DBA、银行/金融运维
前置阅读:《CPU飙到99%?一条命令定位罪魁祸首》
你能得到:3 步定位法 + iostat 4 个核心指标 + 银行 3 个真实案例 + 根因速查表


一、一个容易被忽视的信号

上篇 CPU 排查文章里,我提到过一句话:

如果 topwa(I/O 等待)那列很高,说明 CPU 在等磁盘——这不是 CPU 的锅,去看磁盘

今天就展开讲这个"去看磁盘"。

上周有位读者在后台给我发了一段截图:top 显示 CPU 使用率只有 15%,内存剩了 40%,但系统负载飙到了 30+,应用接口全部超时。

他第一反应是 CPU 有问题。

但其实——CPU 没问题,它在等磁盘。

磁盘 IO 瓶颈有一个很"迷惑"的特征:CPU、内存、网络全看着正常,但系统就是慢。 因为 CPU 的利用率是被 IO 等待稀释了——它大部分时间在"歇着"等磁盘回应,所以 top 里 CPU 的使用率反而不高。

这种问题在银行环境里特别常见,原因我后面说。

先讲排查方法。


二、第一件事:读懂 iostat(大部分人只看一个数字)

SSH 上去,第一件事不是 top,而是:

iostat -xz 1 3

输出示例(这是一个写密集型场景的典型数据):

Device:   rrqm/s  wrqm/s    r/s    w/s   rkB/s   wkB/s  avgrq-sz  avgqu-sz   await  r_await  w_await  %util
sda         0.00   15.00   120    800     500   32000      78.2      8.50   42.3      2.0     45.2   98.5

100 个运维里,80 个只盯着 %util 看到 98.5% 就喊"磁盘满了",然后去找存储厂商。

%util 只是告诉你"磁盘有多忙",没告诉你"它忙得有没有效率"。

真正判断 IO 是否有问题的关键是这 4 个指标

字段 含义 健康线 危险信号
await IO 请求平均响应时间(ms) < 10ms > 30ms,磁盘扛不住了
%util 磁盘忙碌时间占比 < 70% 接近 100%,已达性能上限
r/s, w/s 每秒读/写次数(IOPS) 视磁盘类型 机械盘 > 300 就可能饱和
avgqu-sz 平均 IO 队列长度 < 2 接近设备队列深度上限,说明请求排队严重

💡 补充:NVMe SSD 的特殊性
以上健康线主要针对机械盘(HDD)和 SATA SSD。NVMe SSD 因为多队列并行能力(最多 64K 队列),%util 经常跑到 100% 但 await 只有 0.1ms——它只是"忙",不是"忙不过来"。判断 NVMe 是否有瓶颈,重点看 await,不用太在意 %util

一个很多人不知道的判断技巧

%util 100% 不等于磁盘有问题。

如果 await 只有 2ms,说明磁盘虽然忙,但处理速度极快——它能扛住

真正让人崩溃的组合是:

%util 接近 100% + await 很高 → 磁盘既忙又慢,请求越积越多,雪崩开始了。

记住这个组合,比死记 %util 有用十倍。


三、3 步定位法:从"磁盘慢"到"谁干的"

Step 1:看读写比例——读爆了还是写爆了?

iostat -x 1

观察 r/sw/s 的比例,以及 rkB/swkB/s

  • r/s 远大于 w/s → 读密集型(典型场景:数据库查询、日志检索)
  • w/s 远大于 r/s → 写密集型(典型场景:日志写入、备份同步、数据导入)
  • 两者都高 → 混合压力

这一步决定排查方向,别跳过。

🏦 银行实战 1:某次核心系统批量对账,数据库响应时间从 3ms 飙到 800ms。iostat 显示 r/s 高达 3200,但 w/s 只有 50。纯读压力——后来发现是对账程序没有走缓存,每条记录都直接命中数据库的物理读。加了 Redis 缓存层后,IO 峰值降了 70%。

Step 2:找出哪个进程在疯狂读写

iotop -o

-o 只显示正在做 IO 的进程。按 r 键按读排序,按 w 键按写排序。

一眼就能看到是 MySQL、Java 日志、还是某个备份脚本 在抢磁盘。

如果没装 iotopyum install iotopapt install iotop

不想装也没关系,一行替代命令:

pidstat -d 1 3

🏦 银行实战 2:某次生产环境应用超时,iotop 显示排名第一的不是业务进程,而是 clamd(ClamAV 杀毒引擎)。

原来是安全部门在所有应用服务器上部署了实时文件扫描,每次业务写日志,clamd 就跟读一遍。业务写 1 次,实际产生 2 次 IO。

后果:全行 200 多台应用服务器的 IO 峰值翻倍。

最后改为定时扫描(每小时一次),实时监控改为 inotify 事件触发,IO 峰值降了 45%。

Step 3:定位到具体文件

知道进程 PID 了,看看它在读写哪些文件:

lsof -p <PID> | grep -E "REG|DIR"

或者更硬核的做法——用 strace 抓文件打开事件:

strace -p <PID> -e trace=open,openat -c

等 10 秒按 Ctrl+C-c 模式会按调用次数排序输出,出现最多的一定是最频繁读写的文件路径。

⚠️ 不要用 strace -e trace=read,write -c 来找文件——read/write 系统调用统计里只有 fd(文件描述符数字),没有文件名。要看路径必须抓 open/openat

⚠️ strace 会短暂影响目标进程性能,生产环境慎用,建议在测试窗口或低峰期操作。lsof 无侵入,优先使用。

💡 如果 lsof 找不到可疑的 REG 文件,IO 可能来自匿名内存映射(mmap)或管道。用 vmstat 1 看是否有持续的 si/so(swap in/out),确认是否触发了 swap IO。


四、完整复盘:银行批量备份"雪崩"事件

上面三步讲完,用一个完整的银行案例串一遍。

背景:某国有行清算系统,每周二、四凌晨 2 点准时 IO 飙升,持续 45 分钟到 1 小时。期间核心交易响应时间从 50ms 飙到 3 秒以上。

现象%util 100%,await 飙到 200ms,但 CPU、内存、网络全正常。

排查过程

Step 1iostat -x 1w/s 1200,wkB/s 45MB,写压力极大,读很低。

Step 2iotop -o → 发现 rsync 进程吃掉了 80% 的写 IO。

Step 3lsof -p 17234 → 发现它在把应用日志同步到备份服务器,而且每次都是全量同步当天全部日志(约 80GB)。

根因

之前的运维同事写的备份脚本,每次都用 rsync -av 全量同步,没有用 --link-dest 做增量。随着日志量逐月增长,同步时间从 10 分钟膨胀到 45 分钟,IO 带宽直接被打满。

修复

#!/bin/bash
# 修改前:全量同步,每次传 80GB
rsync -av /app/logs/ backup_server:/backup/logs/

# 修改后:判断是否有昨天的备份,有则增量,无则全量
TODAY=$(date +%Y%m%d)
YESTERDAY=$(date -d "1 day ago" +%Y%m%d)
DEST_BASE=/backup/logs

if [ -d "$DEST_BASE/$YESTERDAY" ]; then
  # 增量:硬链昨天的文件,只传变化的
  rsync -av --link-dest="$DEST_BASE/$YESTERDAY" \
    /app/logs/ "backup_server:$DEST_BASE/$TODAY/"
else
  # 首次或昨天备份不存在:全量
  rsync -av /app/logs/ "backup_server:$DEST_BASE/$TODAY/"
fi

💡 --link-dest 指向的目录必须是已存在的完整备份。首次运行时如果昨天的目录不存在,不加判断直接用会静默退化为全量复制。上面这个脚本做了兼容处理。

同步时长从 45 分钟降回 8 分钟,IO 峰值从 100% 降到 35%。

你看,问题根源不是磁盘慢,而是备份策略设计失误。 换 SSD 只能多撑半年,该崩还是会崩。

这也是为什么银行运维有一句话:“能用策略解决的问题,不要用硬件兜底。”


五、根因速查表(建议收藏)

现象 可能原因 确认命令 解决方向
await 高 + r/s 随机读太多(大量小查询) iotoppt-query-digest 加缓存层、优化慢查询、换 SSD
await 高 + w/s 顺序写或随机写压力大 iotoplsof 看目标文件 异步写、合并写、日志分级
%util 不高但 await 很高 磁盘坏道 / 控制器故障 smartctl -a /dev/sda 换盘,检查阵列卡状态
avgqu-sz 持续 > 10 IO 队列深度过大 iostat -x,检查应用连接池 限流、拆盘、加缓存
iostat 正常但业务慢 文件系统挂了 sync 模式 mount | grep sda 改为 async 挂载
iostat 正常但业务慢 NFS/NAS 后端网络延迟 mount | grep nfsnfsstat 检查 NFS 挂载参数(noatimersize/wsize),排查网络
只在特定时间段飙升 定时任务冲突(备份、跑批) crontab -lls /etc/cron* 错峰执行、改增量策略
只在某块盘上飙升 日志/数据没做分区隔离 iostat -x 对比各设备 把高 IO 业务拆到独立磁盘

六、一张图记住全流程

应用变慢 / 负载高 / 接口超时
         ↓
    vmstat 1 看 wa 列
         ↓
    wa 高?→ iostat -xz 1
         ↓
    看 %util + await 组合
         ↓
    ┌────┴────┐
    ↓         ↓
  读高       写高
    ↓         ↓
  iotop -o  iotop -o
  找读进程   找写进程
    ↓         ↓
  lsof -p   lsof -p
  找文件     找文件
    ↓         ↓
    └────┬────┘
         ↓
    判断根因:慢查询?日志?备份?杀毒扫描?
         ↓
    对症下药(优化策略,而非换硬件)

七、实操练习(5 分钟就能上手)

练习 1:自己制造 IO 压力,再排查它

打开终端,模拟一个写压力:

# 注意:不要写在 /tmp 上!很多系统的 /tmp 是 tmpfs(内存文件系统),
# 写 tmpfs 不经过磁盘,iostat 抓不到变化。
dd if=/dev/zero of=/app/io_test bs=1M count=5000 oflag=direct &

oflag=direct 绕过页缓存,确保 IO 真实落盘,iostat 才能观察到变化。

同时打开另一个终端:

iostat -x 1      # 观察 w/s 和 %util 飙升
iotop -o         # 抓到 dd 进程
lsof -p $(pgrep dd) | grep REG   # 确认它在写 /app/io_test

做完后记得清理:rm -f /app/io_test

练习 2:一行命令找出当前最耗 IO 的进程

# 按磁盘读写总量排序(单位 KB/s)
pidstat -d 1 3 | awk 'NR>3{print $0}' | sort -k3 -rn | head -10

💡 pidstat -d 的列号在不同 sysstat 版本(10.x / 12.x)有差异,用 awk 过滤表头后再排序更稳妥。

把这一行存成 alias io_top,下次直接敲。


八、写在最后

上篇 CPU 文章的结尾我说过一句话:“先定位,后操作。重启是最后的手段,不是第一选择。”

磁盘 IO 问题也一样。

换 SSD 可以掩盖很多问题,但不懂定位的运维,永远在背"换硬件"的锅。

今天的三步法:

  1. iostat -xz 看指标(不要只看 %util,看 await 组合)
  2. iotop -o 抓进程
  3. lsof -p 定位文件

掌握它,你就能在老板喊"找存储厂商"之前,用数据告诉他真相。

这篇文章和上篇 CPU 排查文章是同一系列的,建议两篇连着看——排查系统性能问题,CPU 和 IO 是最先看的一对。


📌 下期预告:《IO 排队太长怎么办?用 blktrace 看内核 IO 栈》


💬 你遇到过最离谱的磁盘 IO 问题是什么?

  • A. 备份脚本把磁盘打满,业务跟着陪葬
  • B. 安全杀毒引擎"帮倒忙",IO 翻倍
  • C. 开发把日志写到了系统盘根分区
  • D. 其他(评论区说说你的故事)

👇 评论区留言,我看到必回。 分享最精彩的 3 位,下期文章开头置顶展示。


关注「云间豹变」,会不定期Linux系统排障技巧(从入门到进阶),系统掌握知识点,应急更高效!

回复关键词 获取内容
命令手册 Linux 运维命令速查 PDF 版
脚本模板 运维脚本打包下载
提示词 AI 运维提示词模板合集

📌 系列文章

  • 《CPU飙到99%?一条命令定位罪魁祸首》—— 银行支付网关事故完整复盘
  • 《线上网络丢包?5步+tcpdump快速定位》—— 薛定谔的故障排查实录
  • 《小王把脚本贴给AI,差点变成安全事件》—— 代码脱敏+安检实操指南
Logo

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。

更多推荐