Linux 服务器磁盘 IO 性能排查指南

Linux 服务器磁盘 IO 性能排查指南

磁盘 IO 瓶颈是服务器性能问题中最隐蔽、也最容易被误判的一类。 很多人看到 load 高、响应慢,第一反应是 CPU 或内存,但实际上 70%+ 的“服务器变慢”最终都能追溯到磁盘 IO 等待(尤其是随机读写场景)。

以下是目前最系统、最高效的排查路径,按快速判断 → 定量分析 → 定位进程 → 根因分类 → 优化闭环的顺序组织。

第一步:30 秒快速判断是否有 IO 瓶颈

顺序命令核心观察指标(异常阈值)如果异常,指向
1iostat -x 1 5 或 iostat -xmdz 1 5%util > 80–90%(单个盘),await > 10–20 ms,svctm 高很可能有 IO 瓶颈
2top / htopwa(iowait)> 15–30% 持续进程在等磁盘
3vmstat 1 5wa > 20%,b(阻塞进程)较多,bi/bo 非零且较大IO 等待队列积压
4uptimeload 高,但 CPU us+sy 不高,wa 高典型“假高负载,真 IO 瓶颈”

一句话判断标准(最重要):

  • %util 接近 100% + await > 10–20ms → 磁盘真的饱和了
  • wa/iowait 高 + %util 不高 → 可能是少量非常慢的 IO 请求拖死整个系统(常见于机械盘或有坏块的 SSD)
  • %util 低 + await 极高 → 单次 IO 延迟极高(网络存储、NFS、坏道、raid 降级)

第二步:区分是哪种 IO 模式导致的瓶颈

用以下命令组合判断 IO 模式:

IO 模式典型特征(iostat -x)常见业务场景关键指标对比
随机读r/s 高,%util 高,await 中等~高,rMB/s 不高数据库(MySQL/PostgreSQL 索引扫描)r/s >> w/s,await 10–50ms
随机写w/s 高,%util 高,await 较高,wMB/s 不高日志写入、Redis AOF、数据库 binlog、WALw/s 高,await > 20–100ms
顺序读rMB/s 很高,%util 中等,await 很低大文件拷贝、备份、视频流读取rMB/s 接近磁盘理论值,await < 5ms
顺序写wMB/s 高,%util 中等~高,await 低~中等大文件写入、Hadoop 数据导入wMB/s 高,await < 10ms
混合负载r/s 和 w/s 都高,%util 高,await 中~高高并发 OLTP 数据库、日志 + 索引同时写r/s ≈ w/s,await 15–60ms

快速口诀

  • r/s 很高 + await 高 → 随机读瓶颈(最常见数据库场景)
  • w/s 高 + await 极高 → 随机写瓶颈(日志、binlog、WAL)
  • %util 高但吞吐(rMB/s + wMB/s)低 → 随机 IO 主导
  • %util 不高但 await 极高 → 单次 IO 极慢(网络存储、坏盘)

第三步:定位是哪个进程/服务在制造 IO

工具命令示例优点 / 使用场景输出重点
iotop(首选)sudo iotop -o -P(只显示有 IO 的)实时、直观,像 top 一样看 IODISK READ / DISK WRITE 列 Top 进程
pidstatpidstat -d 1 5 | sort -k 4 -nr可脚本化、历史统计、精确到线程kB_rd/s、kB_wr/s 最高的进程/线程
blktrace + blkparseblktrace -d /dev/nvme0n1 -a issue极致精确、能看到每个 IO 的详细信息需要后处理,适合深度分析
bpftrace一行脚本追踪特定进程或设备 IO零开销、内核级、可定制延迟分布、热点文件、进程 IO 量
lsof + greplsof /dev/nvme0n1 或 `lsofgrep deleted`找被删除但还在写的文件(最常见日志文件)

推荐组合

  1. 先 iotop -o 看实时谁在写/读最多
  2. 再 pidstat -d 1 10 | sort -k 4 -nr | head -15 确认 10 秒内累计量
  3. 如果看到大量 deleted 文件 → lsof | grep deleted 找元凶

第四步:根因分类与针对性优化

根因分类典型表现(iostat + 进程)常见业务/场景优化优先级 & 方案(从简单到复杂)
日志狂写w/s 高,%util 高,大量写小块nginx access/error、应用 debug 日志1. 降日志级别 2. logrotate + size 限制 3. 异步日志 4. 日志 → tmpfs 或单独盘
数据库慢查询/索引缺失随机读 r/s 高,await 20–100msMySQL/PostgreSQL 未命中索引、全表扫描explain + 加索引、调 innodb_io_capacity、加 buffer pool
binlog / WAL / AOF 同步写随机写 w/s 高,await 极高MySQL sync_binlog=1、Redis appendfsync always调 sync_binlog=0 或 1000、appendfsync everysec、开启 write cache
大量小文件元数据操作r/s 高但 rMB/s 低,dentry/inode slab 膨胀高并发上传小文件、git 仓库、日志切割碎片调 vm.vfs_cache_pressure、用 xfs/ext4 大块、减少小文件数
被删文件仍在写(deleted)iostat 写很高,但 du 看不到占用程序打开日志文件后被 logrotate 删掉重启对应进程,或 kill -USR1 让服务重新打开日志文件
网络存储/NFS/EBS 延迟await 极高(50–500ms),%util 不一定高云盘、NFS、ceph、EBS gp2/gp3 超预算换 io2/io2 Block Express、加大 IOPS、就近部署、加本地缓存
磁盘本身老化/坏块await 极高、偶发 i/o error 日志机械盘老化、SSD 写放大、坏块smartctl 检查健康、坏块重映射、更换磁盘

第五步:验证 & 长期监控建议

验证效果(优化后必须看):

  • iostat -x 1 5 的 %util 和 await 是否显著下降
  • vmstat 的 wa 是否降低
  • 业务延迟 / QPS 是否恢复

长期监控指标(推荐加到 Prometheus / Grafana):

  • node_disk_io_time_seconds_total
  • node_disk_io_time_weighted_seconds_total
  • node_disk_reads_completed_total & writes
  • await / svctm / %util per disk
  • 告警:单个盘 %util > 85% 持续 5min 或 await > 20ms 持续 3min

一句话总结排查口诀:

iostat -x 看 %util + await → iotop/pidstat 找进程 → 区分读/写/随机/顺序 → 看日志/数据库/网络存储/小文件元数据 → 优化写策略/加索引/换盘/分盘

这是目前生产环境中最常使用的磁盘 IO 排查路径,能覆盖 90%+ 的线上 IO 瓶颈场景。

Telegram
Telegram@IDCSELL