%util接近100%却无卡顿,因它仅统计队列非空时间,不反映延迟;SSD/NVMe并发强,高%util可能仅表示高吞吐、深队列;应重点关注await、avgqu-sz及iostat -x扩展指标。

怎么看 iostat 输出里 %util 接近 100% 却没卡顿?
%util 表示设备忙于处理 I/O 请求的时间百分比,但它的计算方式是“任意时刻只要队列里有请求就记为忙”,并不反映实际响应延迟。SSD 或 NVMe 设备并发能力强,%util 高可能只是队列深、吞吐大,而非瓶颈。
真正关键的是 await(平均 I/O 等待时间)和 svctm(服务时间),但注意:在现代内核(2.6.34+)中 svctm 已被弃用,恒为 0,不可信。
- 优先看
await > 10ms(HDD)或> 1ms(SSD)是否持续出现 - 结合
r/s和w/s判断是读多还是写多导致等待升高 - 用
iostat -x 1开启扩展统计,重点关注avgqu-sz(平均队列长度)——若远大于 1,说明应用发请求太快,底层来不及消化
iotop 显示某进程 IO 很高,但 top 里 CPU 占用很低,正常吗?
完全正常。I/O 密集型进程大部分时间在等待磁盘响应,处于 D(uninterruptible sleep)状态,不计入 top 的 CPU 使用率,但会被 iotop 捕获。
要确认是不是真由它引起瓶颈,得看它触发的是随机 I/O 还是顺序 I/O:
- 用
pidstat -d -p查看该进程的1 rkB/s、wkB/s和rrqm/s(读合并数)、wrqm/s(写合并数) - 如果
rrqm/s或wrqm/s很低,而r/s或w/s很高,大概率是小块随机读写(如数据库索引扫描、日志刷盘) - 用
lsof -p看它打开的文件,再结合filefrag -v检查是否文件碎片严重
为什么 fio 测试结果和生产环境 IO 表现差很远?
fio 默认配置模拟的是理想化负载,和真实业务差异极大。常见脱节点包括:
- 没设
--filename指向实际业务数据盘,而是测了系统盘或 tmpfs - 用
-ioengine=sync测延迟,但生产 MySQL/PostgreSQL 默认走libaio+ direct I/O,必须加--ioengine=libaio --direct=1 - 块大小设成
-bs=4k却没配--rw=randread,实际业务混合了读写、不同 offset、带 metadata 操作 - 漏掉文件系统缓存影响:测试前忘执行
echo 3 > /proc/sys/vm/drop_caches,导致反复读同一块数据全走 page cache
更贴近生产的方法是用 blktrace 录制真实 IO 模式,再用 blkparse + fio --read_iolog 回放。
哪些 /proc/diskstats 字段最值得监控?
直接读 /proc/diskstats 可避开工具开销,适合嵌入监控脚本。每行 14 列,关键字段按位置是:
- 第 4 列:
reads completed(成功读请求数),对比第 8 列writes completed看读写比例 - 第 5 列:
reads merged,值大说明内核做了大量读请求合并,通常是顺序读;值小且第 4 列高,倾向随机读 - 第 9 列:
time spent reading (ms),除以第 4 列得平均读响应时间(类似iostat的await) - 第 13 列:
IO in progress(当前活跃 I/O 数),瞬时值 > 1 说明有排队,持续 > 2 基本可判定队列积压
注意:这些是累加值,需两次采样做差分。别直接用第 13 列做告警阈值——它只反映某一纳秒快照,抖动极大。











