目录
-
Linux I/O 性能问题的典型症状
-
I/O 指标总览:什么算“瓶颈”?
-
top:从系统视角判断 I/O 异常
-
iostat:最强 I/O 排查命令的逐行解析
-
sar -d:诊断磁盘压力的时间趋势
-
pidstat -d:定位到底哪个进程在打磁盘
-
实战:生产环境的一次 I/O 瓶颈复盘
-
不同类型的 I/O 问题应该怎么修
-
排查流程图(ASCII 版)
-
命令速查表
-
总结
1. Linux I/O 性能问题的典型症状
出现以下任何一个,你就要怀疑 I/O:
-
loadavg 突然飙升
-
但 CPU 却不高
-
%wa显著上升(10% 就要警惕) -
接口响应时间变长
-
Nginx / MySQL 全部卡顿
-
系统有明显“延迟感”(卡、不流畅、反应慢)
业务表现:
-
日志打印变慢
-
数据库写入延迟增长
-
应用频繁卡在 I/O 调用上
2. I/O 指标总览:哪些值代表“有问题”?
下面是排查 I/O 时最关键的指标及判定标准(极重要)。
| 指标 | 来源 | 判断标准 |
|---|---|---|
%wa | top | >10% 有压力,>30% 基本确定 I/O 被打爆 |
await | iostat | >20ms(SSD)说明有排队,>50ms 非常危险 |
svctm | iostat | 服务时长,本身高表示磁盘慢 |
util | iostat | >60% 高压力,>80% I/O 已经打满 |
tps | iostat | 每秒读写次数,突然暴涨说明有单点打磁盘进程 |
r/s / w/s | iostat | 读/写次数,可判断读写类型 |
rkB/s / wkB/s | iostat | 读写带宽,用于判断是不是高吞吐问题 |
avgqu-sz | iostat | 队列长度 > 1 就说明磁盘在排队 |
3. 用 top 做第一轮判断:系统是否处于 I/O 阻塞?
运行:top -c
重点看:
(1)%wa(I/O wait)
代表 CPU 在等待 I/O 返回的时间百分比。
示例:
%Cpu(s): 3.1 us, 1.2 sy, 0.2 ni, 12.0 id, 38.5 wa, 0.0 hi, 0.1 si, 0.0 st
看到 %wa=38.5%,说明:
✔ CPU 很空闲(id=12%)
✖ 大量进程堵在 I/O 上
✔ 很可能磁盘 I/O 打满了
(2)loadavg 升高,但 CPU 使用率不高
表现为:
-
load=15
-
CPU 使用率=20%
这是典型的:
大量 I/O 阻塞导致的 load 激增
4. iostat:最专业的 I/O 瓶颈诊断工具
运行:iostat -x 1 5
解析关键列(超清晰版)👇
(1)r/s 与 w/s —— 读写操作次数
读操作多:
r/s = 3000 w/s = 100
可能是:
-
日志疯狂输出
-
程序疯狂扫描大文件
-
爬虫读静态资源
写操作多:w/s = 5000
可能是:
-
数据库写压力
-
日志打得太频繁
-
大文件写入
(2)rkB/s 与 wkB/s —— 带宽是否被打爆
例如:rkB/s = 1200000 # 约 1.2GB/s
SSD 基本到极限了。
(3)await —— I/O 等待时间(最重要)
标准(根据 SSD):
| await | 判断 |
|---|---|
| <5ms | 很好 |
| 5–20ms | 正常 |
| 20–50ms | 较高 |
| >50ms | 队列严重阻塞 |
| >100ms | 爆炸级别 I/O 延迟 |
一旦 await > 50ms,你的服务一定会卡。
(4)svctm —— 服务时间
如果:
-
svctm 很低
-
await 很高
说明磁盘本身不慢,但 排队很长。
(5)util —— 使用率
非常关键:
util:表示磁盘繁忙时间(100% 意味着被打满)
标准:
util > 80% = I/O 饱和 util > 95% = 完全爆满
完整示例(危险)
Device: r/s w/s rkB/s wkB/s await svctm util nvme0n1 3100 4200 123000 222000 65.1 0.5 99.8
结论:
✔ 大量读写
✔ await 60ms → 排队严重
✔ util = 99.8 → I/O 被爆掉了
5. sar -d:看 I/O 压力的趋势(非常重要)
sar -d 1 5
你可以看到:
-
哪个时间点 I/O 开始攀升
-
哪些设备被写爆
-
i/o 负载是否周期性出现(如日志轮转)
示例(占位图):
[图:I/O 延迟随着时间逐步增加]
6. pidstat -d:定位哪个进程在打磁盘
这是很多人不会用但极其强大的命令。
pidstat -d 1
你会看到:
-
每个进程的读写数据量
-
哪个程序读写最频繁
-
哪个进程导致磁盘忙碌
输出示例:
PID kB_rd/s kB_wr/s Command 1234 0 32000 mysqld 2222 1000 0 python3 4321 0 29000 java
一下子就定位了:
✔ MySQL & Java 写太猛
✔ 某 Python 任务大量读取大文件
7. 实战案例:一次线上 I/O 瓶颈导致全链路卡死
(本章节是文章最容易火的部分,故事 + 技术细节)
7.1 故障表现
-
业务接口从 200ms → 1500ms
-
load 从 3 → 20
-
服务频繁超时
-
登录服务器很卡
7.2 第一轮排查(top)
%wa = 42%
I/O 有大问题。
7.3 第二轮排查(iostat)
await = 70ms
util = 99.9%
马上确定是磁盘瓶颈。
7.4 第三轮排查(pidstat)
结果:
PID kB_wr/s COMMAND 1221 40000 java 3444 38000 java
定位到:
✔ Java 服务开启 debug 日志 → 打爆磁盘!
之前有人把日志级别改成了:DEBUG
导致每秒写入几十 MB。
7.5 问题解决
改回:INFO
重启服务后:
-
util 从 99% → 15%
-
await 从 70ms → 3ms
-
业务延迟从 1500ms → 120ms
服务器瞬间复活 💥
8. 常见 I/O 问题类型与解决方案
下面是生产环境最常见的 8 类 I/O 问题及解决策略👇
8.1 日志疯狂写入(最常见)
症状:
-
w/s 涨
-
wkB/s 涨
-
util=100%
解决:
-
降低日志级别
-
使用异步日志(logback async)
-
写本地 → 分批发送到日志服务器
-
日志分盘
8.2 数据库写压力过大
解决:
-
批量写入
-
缓存
-
索引优化
-
SSD 升级 NVMe
8.3 大量爬虫导致静态资源读压力
解决:
-
CDN
-
fail2ban
-
限流
8.4 某脚本疯狂读写文件
解决:
-
找脚本
-
优化算法
-
避免扫描大目录
8.5 swap 被用满(极其恐怖)
表现:
-
系统卡得无法 SSH
-
load 飙升
-
iowait 超高
解决:
-
禁用 swap
-
或增大内存
8.6 RAID 卡瓶颈 / HDD 机械盘太慢
解决:
-
升级 SSD/NVMe
-
RAID10
-
使用 LVM 缓存(lvmcache)
8.7 Docker overlay2 导致的文件系统慢
解决:
-
使用 volumes
-
关闭大量小文件写入
9. I/O 瓶颈排查流程图(ASCII 版)
┌───────────────┐ │ 系统变慢 │ └──────┬────────┘ ↓ ┌──────────────┐ │ top 看 %wa │ └──────┬────────┘ ↓ ┌────────────────────────────────┐ │ %wa > 10% → I/O 问题可能存在 │ └──────┬─────────────────────────┘ ↓ ┌──────────────────────────────┐ │ iostat -x 看 await / util │ └──────┬────────────────────────┘ ↓ ┌────────────────────────────────┐ │ util > 80% → I/O 打满 │ └──────┬─────────────────────────┘ ↓ ┌──────────────────────────────────┐ │ pidstat -d 找进程 │ └──────────────────────────────────┘
10. 命令速查(最有用的部分)
top vmstat 1 iostat -x 1 5 sar -d 1 5 pidstat -d 1 iotop du -sh * df -h dmesg | grep -i error
11. 总结
I/O 性能问题一般有以下特点:
-
symptom:load 高、CPU 不高
-
实质:磁盘被打满
-
根因:日志 / DB / 大文件读写 / 脚本 / 爆量请求 / swap
排查路线始终是:
top → iostat → sar → pidstat → 找进程 → 找根因 → 解决
394

被折叠的 条评论
为什么被折叠?



