磁盘i/o优化第一步是用fio测准真实性能:需按业务场景选随机读写(如数据库4k iops与p99延迟)或顺序读写(如日志1m吞吐),必须加direct=1绕过缓存,区分文件系统与裸设备测试,并关注iops、bw和clat百分位延迟。

磁盘I/O优化的第一步,是用fio测准真实性能。很多工程师一上来就调内核参数或改调度器,结果发现瓶颈根本不在软件层——而是磁盘本身在随机写时只有800 IOPS,远低于标称值。fio能暴露这种硬伤,关键在于参数组合要贴合业务场景,不能只跑默认命令。
明确测试目标:随机还是顺序?对应什么业务?
随机读写和顺序读写反映完全不同的硬件能力:
- 随机I/O(randread/randwrite):模拟数据库、虚拟机、容器存储等典型负载,核心看4K块的IOPS和尾延迟(如p99 latency ≤ 10ms)。SSD在此类场景优势明显,而HDD会因寻道时间飙升导致IOPS骤降。
- 顺序I/O(read/write):适用于日志写入、备份归档、大文件转存等场景,重点看吞吐量(MB/s),比如NVMe盘能否跑到6000 MB/s以上。
- 别混淆混合模式:
rw=randrw需配合rwmixwrite=30明确读写比例,否则fio默认50/50,可能偏离MySQL写多读少或Redis读多写少的真实分布。
绕过缓存,直测物理设备真实性能
不加direct=1的测试结果基本无效——它让数据走内核page cache,测出来的是内存速度,不是磁盘速度。
- 对文件系统测试:指定
filename=/mnt/data/testfile,确保该分区挂载时未启用barrier=0或noatime以外的激进优化; - 对裸设备测试(更推荐):
filename=/dev/nvme0n1,但必须确认设备未挂载、无LVM或RAID占用,否则会破坏数据; - 加
invalidate=1保证每次测试前清空page cache,避免上一轮残留影响本轮结果。
关键参数组合示例(可直接复用)
以下命令均基于libaio引擎(需装libaio-devel),适合生产环境压测:
-
OLTP数据库随机读基准:
fio -name=randread-4k -ioengine=libaio -direct=1 -thread -rw=randread -bs=4k -size=20G -iodepth=32 -numjobs=4 -runtime=120 -group_reporting -eta-new
→ 模拟4线程、队列深32的高并发小块读,输出IOPS和p99延迟。 -
日志盘顺序写极限测试:
fio -name=seqwrite-1M -ioengine=libaio -direct=1 -thread -rw=write -bs=1M -size=50G -iodepth=16 -numjobs=2 -runtime=180 -group_reporting
→ 大块连续写,观察是否持续稳定在标称带宽,同时检查lat是否突增(提示设备开始限速或GC介入)。 -
SSD稳态随机写预热+测试:
先执行预热:fio -name=warmup -ioengine=libaio -direct=1 -rw=randwrite -bs=4k -size=100G -iodepth=32 -numjobs=8 -runtime=600;
再运行正式测试,避免新盘因缓存/磨损均衡未启动导致IOPS虚高。
看懂fio报告里的三个核心数字
测试结束后,fio输出中真正要盯住的是:
-
IOPS:例如
iops=12480,即每秒完成1.2万次4K IO请求; -
BW(带宽):如
bw=48.8MiB/s,对应IOPS × 块大小(12480 × 4K ≈ 48.8MiB/s); -
lat(延迟):重点关注
clat percentiles段,比如99.00th=[12500]表示99%的IO完成时间≤12.5ms;若p99跳到50ms以上,说明设备已出现排队或介质老化。










