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 数据说话,避免盲目堆参数。