Linux 磁盘 IO 性能瓶颈分析方法

7次阅读

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

Linux 磁盘 IO 性能瓶颈分析方法

怎么看 iostat 输出里 %util 接近 100% 却没卡顿?

%util 表示设备忙于处理 I/O 请求的时间百分比,但它的计算方式是“任意时刻只要队列里有请求就记为忙”,并不反映实际响应延迟。SSD 或 NVMe 设备并发能力强,%util 高可能只是队列深、吞吐大,而非瓶颈。

真正关键的是 await(平均 I/O 等待时间)和 svctm(服务时间),但注意:在现代内核(2.6.34+)中 svctm 已被弃用,恒为 0,不可信。

  • 优先看 await > 10ms(HDD)或 > 1ms(SSD)是否持续出现
  • 结合 r/sw/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/swkB/srrqm/s(读合并数)、wrqm/s(写合并数)
  • 如果 rrqm/swrqm/s 很低,而 r/sw/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 列得平均读响应时间(类似 iostatawait
  • 第 13 列:IO in progress(当前活跃 I/O 数),瞬时值 > 1 说明有排队,持续 > 2 基本可判定队列积压

注意:这些是累加值,需两次采样做差分。别直接用第 13 列做告警阈值——它只反映某一纳秒快照,抖动极大。

text=ZqhQzanResources