Linux 磁盘 I/O 性能调优实战:从 I/O 调度器、iostat 到 fio 压测的完整链路 原创

温馨提示:
本文最后更新于 2026-11-05,已超过 0 天没有更新。 若文章内的图片失效(无法正常加载),请留言反馈或直接 联系我。

Linux 磁盘 I/O 性能调优实战:从 I/O 调度器、iostat 到 fio 压测的完整链路

磁盘 I/O 是服务器性能的常见瓶颈。当 CPU 空闲、负载却居高不下,或数据库查询缓慢时,往往问题就出在存储层。本文从 I/O 调度器选择、性能观测到压测验证,给出一条可落地的完整调优链路。

一、先理解磁盘 I/O 的构成

一次磁盘读写请求会经过:文件系统 → 块设备层 → I/O 调度器 → 磁盘驱动 → 物理介质。其中 I/O 调度器决定请求如何排队与合并,直接关系吞吐量与延迟的取舍。现代内核默认使用 mq-deadline 或 none(对于 NVMe),而老式的 cfq 已被移除。

二、选择合适的 I/O 调度器

查看当前调度器:

cat /sys/block/sda/queue/scheduler

不同场景的选择原则:

设备类型 推荐调度器 理由
NVMe SSD none 硬件已做队列管理,内核无需额外调度
SATA SSD / 数据库盘 mq-deadline 保证请求延迟,读写分离
机械硬盘 HDD mq-deadline / bfq 合并请求,减少寻道,提升吞吐

临时切换(立即生效):

echo none > /sys/block/nvme0n1/queue/scheduler

永久生效则写入 /etc/udev/rules.d/ 或使用 systemd 单元在启动时设置,避免重启失效。

三、观测 I/O 性能的常用工具

iostat 是最直接的观测入口,重点关注 await(平均等待时间)、svctm(服务时间)与 %util(设备利用率):

iostat -x 1 5
  • %util 接近 100%:设备已饱和,需横向扩容或升级硬件。
  • await 远大于 svctm:队列过长,请求在排队。
  • util 不高但性能差:可能是调度器或文件系统层的问题。

配合 iostat -x /dev/sda 2 持续采样,结合 pidstat -d 定位哪个进程在制造 I/O 压力。

四、用 fio 做基准压测

fio 是业界标准的 I/O 压测工具,可模拟顺序读、随机写等真实负载:

fio --name=randwrite --rw=randwrite --bs=4k --size=2G \
    --numjobs=4 --iodepth=32 --runtime=30 \
    --direct=1 --ioengine=libaio

关键参数含义:bs 块大小(数据库常见 4k/16k)、iodepth 队列深度(越高越能压出延迟)、direct=1 绕过页缓存测裸盘性能。对比压测前后的 iops 与 latency 即可量化调优收益。

五、进阶调优手段

  • 队列深度调整:/sys/block/sda/queue/nr_requests 增大可提升吞吐,但会推高延迟,需权衡。
  • read ahead:blockdev --setra 提升顺序读场景(如日志、大文件)性能。
  • 文件系统挂载参数:ext4 使用 noatime 减少元数据写;xfs 对高并发更友好。
  • 关闭不必要的日志同步:对可接受数据丢失风险的场景,可用 data=writeback 降低写放大。

六、验证与总结

调优不是”一次到位”,而是”观测 → 调整 → 压测 → 再观测”的循环。先明确业务是延迟敏感型(在线交易)还是吞吐型(日志采集),再据此选择调度器与队列参数。建议每次只改一个变量,用 fio 数据说话,避免盲目堆参数。