3. 排查工具:iostat、iotop、pidstat、blktrace、fio
说到磁盘IO排查,工具就是我们的眼睛和手。没有趁手的家伙,再牛的理论也白搭。这一章我把自己压箱底的五个工具拿出来,挨个儿给你讲透。
你可能会问:一个iostat不就够了吗?说实话,不够。每个工具看问题的角度不一样。我打个比方——iostat是站在马路上看车流,iotop是盯着每辆车看谁在超速,pidstat能告诉你司机是谁,blktrace连发动机的每个冲程都能录下来,而fio嘛,是直接造一辆车去压马路。
3.1 iostat — 磁盘IO的“心电图”
iostat是我用得最频繁的工具,没有之一。每次接到性能告警,我第一件事就是敲iostat -x 1。为什么加-x?因为默认模式信息太少,扩展模式才能看到真正的细节。
# 每1秒刷新一次,显示扩展统计
iostat -x 1
# 只看某个设备
iostat -x sda 1
输出里字段很多,但真正关键的没几个。我列个表,你照着盯就行:
| 字段 | 含义 | 警戒线 |
|---|---|---|
%util |
磁盘忙绿百分比 | > 80% 要警惕,> 90% 基本饱和 |
r/s, w/s |
每秒读写请求数 | 跟硬件极限比,SSD通常能到几万 |
r_await, w_await |
平均IO等待时间(毫秒) | > 10ms 算慢,> 50ms 问题严重 |
avgrq-sz |
平均IO大小(扇区) | 太小说明碎片化,太大可能批量操作 |
svctm |
平均服务时间 | 接近硬件极限,SSD通常 < 1ms |
r_await和aqu-sz(平均队列长度)。
举个例子。有一次线上MySQL写入突然变慢,我上去一看:%util 85%,w_await 45ms。嗯,磁盘确实忙,但还没到极限。再一看avgrq-sz只有8,说明每次写的数据量很小但频率极高。这明显是应用层的问题——后来发现是某个日志模块把fsync调用写进了热点路径。
3.2 iotop — 揪出“吃IO”的进程
iostat告诉你磁盘忙,但谁在搞事?iotop就是干这个的。它有点像top命令,但关注的是IO。
# 安装(CentOS)
yum install iotop
# 运行,只看实际IO的进程
iotop -oP
-o只显示有IO的进程,-P显示进程而非线程。这两个参数我每次都加,不然满屏的0看着心烦。
输出里重点关注两列:DISK READ和DISK WRITE,单位是字节/秒。还有IO>列,显示的是IO优先级。
我记得有一次帮客户排查,iostat显示sdb的%util一直在95%以上。打开iotop一看,好家伙,一个叫log_aggregator的进程在疯狂写数据。一问才知道,这个进程每秒钟把几百MB的日志从各个节点拉过来再压缩写入。后来改成异步批量写入,IO直接降了70%。
3.3 pidstat — 进程级别的IO统计
pidstat是sysstat包里的,跟iostat同门。它能告诉你每个进程具体的IO行为,比iotop更精细一些。
# 查看进程IO统计,每秒刷新
pidstat -d 1
# 只看某个PID
pidstat -d -p 12345 1
关键字段:
kB_rd/s— 每秒读千字节数kB_wr/s— 每秒写千字节数cswch/s— 每秒上下文切换次数(这个很关键,IO密集往往伴随高上下文切换)
为什么有了iotop还要pidstat?因为pidstat可以跟其他统计一起看。比如我经常同时开两个窗口:一个跑pidstat -d 1,另一个跑pidstat -u 1。这样能同时看到进程的IO和CPU消耗,定位问题更准。
pidstat -d -p ALL 1 | grep -E "PID|awk"可以过滤出IO量最大的几个进程。我写了个小脚本,每10秒抓一次top5,记录到日志里。出问题时翻一翻,往往能找到规律。
3.4 blktrace — IO事件的“黑匣子”
前面几个工具都是看统计值,blktrace不一样。它能记录每个IO请求从产生到完成的完整生命周期。说白了,就是给磁盘IO装了个监控摄像头。
# 跟踪sda设备,跟踪时间10秒
blktrace -d /dev/sda -o trace -w 10
# 分析结果
blkparse trace -o trace.txt
blktrace的输出分几个阶段:
- Q — IO请求入队列
- G — 请求合并
- I — 请求插入调度队列
- D — 请求下发到驱动
- C — 请求完成
你看,从Q到C的时间就是IO的完整延迟。如果Q到D的时间很长,说明调度器或队列有问题;如果D到C很长,那多半是硬件慢。
有一次我遇到个诡异问题:磁盘偶尔会卡住几秒钟。iostat看不出规律,iotop也抓不到。最后用blktrace抓了30秒,发现每隔15秒左右,所有IO请求的D到C时间突然飙升到2秒以上。查了一圈,原来是磁盘固件在做内部垃圾回收。后来换了企业级SSD,问题消失。
3.5 fio — 磁盘性能的“压力测试仪”
fio不是排查工具,是测试工具。但为什么放在这里?因为排查问题时,你经常需要知道“磁盘到底能跑多快”。没有基准值,你怎么判断当前是不是慢?
# 随机读测试
fio --name=randread --ioengine=libaio --rw=randread --bs=4k --size=1G --numjobs=4 --runtime=30 --group_reporting
# 随机写测试
fio --name=randwrite --ioengine=libaio --rw=randwrite --bs=4k --size=1G --numjobs=4 --runtime=30 --group_reporting
# 混合读写
fio --name=rw --ioengine=libaio --rw=randrw --rwmixread=70 --bs=4k --size=1G --numjobs=4 --runtime=30 --group_reporting
输出里重点看:
- IOPS — 每秒IO次数,随机读写的关键指标
- BW — 带宽,顺序读写的关键指标
- lat (usec) — 延迟分布,看p99和p99.9
| 测试场景 | 典型IOPS(企业级SSD) | 典型延迟 |
|---|---|---|
| 4K随机读 | 50万 - 100万 | 100-300μs |
| 4K随机写 | 10万 - 30万 | 200-500μs |
| 128K顺序读 | 带宽 2-5 GB/s | 延迟较低 |
工具选型指南
说了这么多,到底什么时候用哪个?我画了张图,帮你理清思路:
总结一下我的使用习惯:
- 日常监控:iostat + pidstat,轻量无负担
- 定位进程:iotop快速扫描,pidstat精确抓取
- 疑难杂症:blktrace上阵,但控制好采样时间
- 性能评估:fio建立基线,定期对比