Linux 磁盘 I/O 问题定位技巧

2次阅读

判断i/o瓶颈应优先看await(>10–20ms需警惕)和avgqu-sz(持续>1且await升高说明排队),而非%util;svctm已不可靠,需结合iotop -opa、pidstat -d及/proc/pid/io等多工具分层定位。

Linux 磁盘 I/O 问题定位技巧

怎么看 iostat 输出里哪个设备真在拖慢系统

直接看 %util 容易误判——它只反映设备忙闲比例,不等于瓶颈。真正关键的是 await(平均每次 I/O 等待毫秒数)和 svctm(实际服务时间),但注意:现代内核里 svctm 已不可靠,await 显著高于 10–20ms 就值得怀疑。

实操建议:

  • iostat -x 1 每秒刷新,重点关注 r_awaitw_awaitavgqu-sz(平均队列长度)。若 avgqu-sz 长期 > 1 且 await 持续升高,说明请求在排队
  • 对比同类型设备:比如都是 NVMe 盘,sdbawaitsda 的 5 倍,优先查 sdb 对应的文件系统或应用逻辑
  • 别只盯 sda——有些系统把日志盘、数据库数据盘分在 nvme0n1p2 这类名字上,iostat 默认不显示完整设备名,加 -d 参数或看 /proc/partitions

pidstat -d 找出吃 I/O 的进程,但为什么经常漏掉

pidstat -d 只统计进程级的读写字节数,对短时高频小 IO(比如每秒几千次 4KB 写)、内存映射文件(mmap)、或通过管道/套接字间接触发磁盘写入的场景,基本不体现。

实操建议:

  • 先跑 pidstat -d 1 看大头,再立刻补一句 iotop -oPa(只显示实际在做 I/O 的线程,-P 显示进程名,-a 显示累计 I/O)
  • 注意 iotop 默认按实时吞吐排序,但“高吞吐”不等于“高延迟贡献者”。一个每秒写 1MB 的日志进程,可能比每秒写 100KB 但卡住数据库事务的进程更无害
  • 如果 iotop 里看到 javapostgres 占着高 I/O,别急着优化代码——先查它是否在刷脏页:cat /proc/<pid>/io | grep write_bytes</pid>,再对比 pg_stat_bgwriterpostgresql)或 jvm 的 GC 日志中是否频繁触发 CMS/Full GC 导致大量对象落盘

lsof +D 扫目录很慢,还可能卡死,有没有轻量替代

lsof +D /var/log递归遍历所有子目录并检查每个打开文件的 inode,遇到 NFS 挂载点、坏块或权限受限路径极易卡住。而且它只告诉你“谁打开了文件”,不告诉你“此刻正在读写哪部分”。

实操建议:

  • find /var/log -xdev -type f -printf '%p %T@n' | sort -k2nr | head -20 快速定位最近被修改的文件,再用 lsof /var/log/app.log 精准查单个文件
  • 想看实时写入位置?sudo dd if=/dev/zero of=/tmp/test bs=4k count=100 oflag=sync 后立刻 cat /proc/diskstats,对比前后变化,能快速验证是不是某块盘响应异常
  • 更准的办法是用 perf record -e block:block_rq_issue,block:block_rq_complete -a sleep 5 抓底层块层事件,但需要 root 权限且输出需解析,日常排查够用,别一上来就上这个

为什么 vmstatbi/bo 很低,但磁盘还是卡

bi(blocks in)和 bo(blocks out)是每秒传输的块数(默认 1KB/块),数值低只说明吞吐量小,不代表延迟低。比如一个应用每秒只发 10 次写请求,但每次都要等 200ms 才返回,bi 可能才 10,iostat 却显示 await=200

实操建议:

  • 不要单独看 vmstat 判断 I/O 健康,它缺延迟维度。必须配合 iostat -xawaitsvctm(尽管后者不准,但趋势可参考)
  • 如果 bi/bo 低 + iostat%util 也低 + await 却高,大概率是存储侧问题:后端 RAID 卡电池故障导致写缓存禁用、SAN 存储 QoS 限速、或云盘 IOPS 配额耗尽(如 AWS gp3 未配置足够 iops
  • 查云环境时,cat /sys/block/nvme0n1/device/model 看是不是 Amazon Elastic Block Store,然后立刻去控制台看 CloudWatch 中 VolumeIdleTimeVolumeQueueLength,这两个比本地工具更准

复杂点在于:I/O 延迟可能横跨内核块层、驱动、HBA、阵列控制器、网络(iSCSI/NVMe-oF)、甚至远端存储节点。定位时得一层层剥,别指望一个命令扫清全场。

text=ZqhQzanResources