Linux 磁盘 IO 性能问题排查指南

一、问题现象

磁盘 IO 问题通常表现为:

  • 系统响应缓慢,尤其是文件操作
  • 应用程序读写超时
  • top命令中%wa(io wait) 持续偏高
  • 日志中出现 I/O timeout 错误
  • 数据库查询变慢或卡住

二、快速诊断命令

2.1 查看整体 IO 状态

1
2
3
4
5
6
7
8
# 查看 IO 等待占比(%wa 高说明 IO 是瓶颈)
top

# 实时查看 IO 统计
iostat -x 1

# 查看进程 IO 情况
iotop -oPa

2.2 关键指标解读

指标 含义 正常值
%util 磁盘利用率 < 80%
await 平均等待时间 (ms) < 10ms
svctm 平均服务时间 (ms) < 5ms
%wa CPU IO 等待 < 20%

三、定位问题进程

3.1 使用 iotop 找出 IO 大户

1
2
3
4
5
# 按 IO 排序显示进程
iotop -oPa

# 只监控特定进程
iotop -oPaP $(pgrep mysql)

3.2 使用 pidstat 监控进程 IO

1
2
3
4
5
# 每秒采样一次,监控所有进程
pidstat -d 1

# 监控特定 PID
pidstat -d -p <PID> 1

3.3 查看进程打开的文件

1
2
3
4
5
# 查看进程打开的文件描述符
lsof -p <PID>

# 查看进程 IO 统计
cat /proc/<PID>/io

四、磁盘性能测试

4.1 使用 dd 测试顺序读写

1
2
3
4
5
6
# 写测试(1GB 文件)
dd if=/dev/zero of=/tmp/testfile bs=1M count=1024 conv=fdatasync

# 读测试(清除缓存后)
echo 3 > /proc/sys/vm/drop_caches
dd if=/tmp/testfile of=/dev/null bs=1M

4.2 使用 fio 进行综合测试

1
2
3
4
5
6
7
8
9
10
11
12
13
# 安装 fio
apt install fio # Debian/Ubuntu
yum install fio # CentOS/RHEL

# 随机读测试
fio --name=randread --ioengine=libaio --iodepth=1 \
--rw=randread --bs=4k --direct=1 --size=1G \
--numjobs=4 --runtime=60 --group_reporting

# 随机写测试
fio --name=randwrite --ioengine=libaio --iodepth=1 \
--rw=randwrite --bs=4k --direct=1 --size=1G \
--numjobs=4 --runtime=60 --group_reporting

五、常见问题与解决方案

5.1 磁盘利用率过高

现象: %util 接近 100%

排查:

1
2
3
4
5
6
# 查看哪个分区 IO 最高
iostat -x 1

# 查看该分区挂载点
df -h
mount | grep <device>

解决:

  • 迁移高 IO 负载到其他磁盘
  • 增加磁盘缓存(调整 vm.dirty_ratio)
  • 优化应用程序 IO 模式

5.2 大量小文件读写

现象: IOPS 高但吞吐量低

解决:

  • 合并小文件操作
  • 使用异步 IO
  • 考虑使用 SSD 或 NVMe
  • 调整文件系统参数(noatime)

5.3 磁盘队列过长

现象: avgqu-sz 持续大于 1

排查:

1
2
# 查看队列深度
iostat -x 1 | grep -A1 Device

解决:

  • 降低并发 IO 请求
  • 增加磁盘数量(RAID/LVM)
  • 升级更快存储设备

5.4 交换分区频繁使用

现象: 磁盘 IO 高且 swap 使用率高

排查:

1
2
free -h
vmstat 1

解决:

  • 增加物理内存
  • 调整 swappiness:sysctl vm.swappiness=10
  • 优化应用程序内存使用

六、优化建议

6.1 文件系统挂载参数

1
2
# /etc/fstab 添加优化参数
/dev/sda1 /data ext4 noatime,nodiratime,commit=60 0 2
参数 作用
noatime 不更新访问时间
nodiratime 不更新目录访问时间
commit=60 60 秒提交一次(默认 5 秒)

6.2 内核参数调优

1
2
3
4
5
6
7
8
9
10
# /etc/sysctl.conf
# 增加脏页回写阈值
vm.dirty_ratio = 20
vm.dirty_background_ratio = 10

# 减少交换倾向
vm.swappiness = 10

# 增加预读
vm.read_ahead_kb = 4096

6.3 应用层优化

  • 使用连接池减少数据库 IO
  • 批量写入代替频繁小写入
  • 使用缓存层(Redis/Memcached)
  • 异步处理非关键 IO 操作

七、监控告警配置

7.1 Prometheus 监控指标

1
2
3
4
5
6
7
8
9
# 磁盘 IO 利用率
node_disk_io_time_seconds_total

# 磁盘读写速率
node_disk_read_bytes_total
node_disk_written_bytes_total

# IO 等待时间
node_disk_io_time_weighted_seconds_total

7.2 告警规则示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
groups:
- name: disk_io
rules:
- alert: DiskIOLatencyHigh
expr: rate(node_disk_io_time_weighted_seconds_total[5m]) / rate(node_disk_io_time_seconds_total[5m]) > 0.8
for: 5m
labels:
severity: warning
annotations:
summary: "磁盘 IO 延迟过高"

- alert: DiskUtilizationHigh
expr: rate(node_disk_io_time_seconds_total[1m]) > 0.9
for: 10m
labels:
severity: critical
annotations:
summary: "磁盘利用率持续高于 90%"

八、排查流程图

1
2
3
4
5
6
7
8
9
10
11
12
13
发现 IO 问题

top 查看%wa 是否高?
↓是
iostat -x 1 定位磁盘

iotop 找出问题进程

分析进程行为

├─ 正常业务高峰 → 考虑扩容/优化
├─ 异常进程 → 终止/限制
└─ 配置问题 → 调整参数

九、总结

磁盘 IO 问题排查核心步骤:

  1. 确认现象:通过 top/iostat 确认 IO 是瓶颈
  2. 定位磁盘:找出 IO 最高的设备
  3. 定位进程:用 iotop 找出 IO 大户
  4. 分析原因:是正常负载还是异常行为
  5. 采取措施:优化配置/限制进程/扩容硬件

记住:IO 问题往往是表象,根本原因可能是内存不足、应用设计缺陷或硬件老化。