Linux 磁盘 I/O 性能分析与优化

1次阅读

用 iotop -o 实时定位狂写磁盘进程,需 root 权限;iostat -x 关注 await、avgqu-sz 而非 %util;dd 测速需用 fio 模拟真实负载;调优 vm.dirty_* 参数须兼顾刷盘平滑性与设备特性。

Linux 磁盘 I/O 性能分析与优化

怎么快速定位哪个进程在狂写磁盘

iotop 是最直接的办法,它像 top 一样实时显示每个进程的 I/O 读写速率。注意加 -o 参数只显示有实际 I/O 的进程,否则一休眠进程会干扰判断;如果没装,debian/ubuntusudo apt install iotopcentos/RHEL 用 sudo yum install iotop(或 dnf)。别依赖 pshtop——它们根本不暴露 I/O 带宽数据。

  • 运行时需 root 权限,普通用户看不到其他进程的 I/O 细节
  • 默认按 I/O 总量排序,但实际瓶颈常是 IOPS(每秒请求数)而非吞吐量,可按 P 键切换到“IO_RATE”列观察写延迟敏感型负载
  • 某些容器环境(如使用 io.weight cgroup v2)下,iotop 显示的数值可能偏低,此时得结合 cat /sys/fs/cgroup/io.stat 手动核对

为什么 iostat -x 1 的 %util 接近 100% 却没卡死

%util 只表示设备忙的时间占比,并不等于饱和。SSD 和 NVMe 设备能并行处理成百上千个队列请求,即使 %util 满了,只要 await(平均 I/O 等待时间)低、svctm(服务时间)稳定,系统响应就正常。真正危险的是 r_awaitw_await 持续超过 10ms(机械盘)或 1ms(NVMe)。

  • iostat -x 1 中重点盯 avgqu-sz(平均队列长度):持续 > 1 表示请求开始排队;> 4 通常说明底层设备已吃紧
  • %util 对 NVMe 设备参考价值极低,建议直接看 rqm/s(合并请求数)和 rrqm/s/wrqm/s 判断 I/O 合并效率
  • 虚拟机里看到高 %util,先检查宿主机的 blktrace 输出,可能是上层存储(如 ceph、LVM thin pool)导致的假性繁忙

dd 测速结果为什么和实际应用差十倍

dd 默认用小块(512B–4KB)、同步写(conv=fdatasync 才算真正落盘),测出来的是随机写或小文件写极限,而数据库、日志服务多是混合读写+大块顺序写+缓存参与。它反映的是“最差路径”,不是典型负载。

  • 模拟数据库场景:用 fio --name=randwrite --ioengine=libaio --rw=randwrite --bs=16k --numjobs=4 --runtime=60
  • 绕过页缓存加 --direct=1,否则 dd 结果全是内存带宽,跟磁盘无关
  • 生产环境禁用 oflag=sync 测吞吐——这会让每次写都等刷盘,压垮队列深度,测出的是延迟而非吞吐

调整 vm.dirty_ratio 后反而更卡了

调高这个值(比如从 20 改到 60)本意是让内核攒更多脏页再刷盘,提升吞吐。但若应用本身写入节奏不均(例如批量导入后突发 flush),会导致刷盘时集中触发大量 writeback,造成数秒级 I/O 尖峰,表现为周期性卡顿。

  • 优先调 vm.dirty_background_ratio(后台异步刷起点),设为 10–15,让刷盘更平滑
  • 配合 vm.dirty_expire_centisecs(脏页存活上限,默认3000=30秒),避免脏页积压太久
  • SSD 上慎用极高 dirty_ratio,因频繁擦除+写放大可能加速磨损,且 TRIM 命令无法及时回收空间

事情说清了就结束。I/O 优化不是调几个 sysctl 就完事,关键在分清「是设备瓶颈、队列瓶颈,还是应用行为失当」——同一组参数,在 mysqlkafka 上效果可能完全相反。

text=ZqhQzanResources