暗色模式

fio 磁盘性能测试:从顺序吞吐到 4K 随机 IOPS 的存储基准

技术教程
2026-09-06
11
0
本文要点
  • fio 是 Linux 存储基准测试的事实标准工具:随机/顺序、块大小、队列深度、直接 IO 全部可精确控制,比 dd 更能模拟数据库、虚拟机这类真实负载
  • 核心参数组合:--rw(read/write/randread/randwrite)+ --bs + --iodepth + --ioengine=libaio + --direct=1(绕过页缓存,不加测到的是内存速度)
  • 实测一台 40G 普通云盘(Ubuntu 24.04、fio 3.36):顺序 1M 块读写在 112~114 MiB/s,4K 随机 iodepth=32 下 IOPS 2272(读)/2229(写)
  • 延迟要看百分位而非平均值:实测 4K 随机读 50th≈10.6ms、99th≈20.6ms;且平均延迟≈队列深度÷IOPS,与利特尔法则完全吻合
  • ⚠️ --filename 必须指向测试文件(如 /root/fio-test),绝不能写成 /dev/vda 这类整盘设备——fio 会直接覆写块设备,数据全毁
  • 全部命令在 Ubuntu 24.04.4(内核 6.8、fio 3.36)上真实执行,截图即真实输出

fio 磁盘性能测试:从顺序吞吐到 4K 随机 IOPS 的存储基准

买云服务器、选数据盘、评估数据库性能时,最先想搞清楚的问题就是「这块盘到底多快」。顺序拷大文件能到多少 MB/s?4K 随机小 IO 能扛多少 IOPS?延迟分布是集中在 1ms 还是拖到 20ms?这些数字用 dd 粗测只能得到严重失真的结果——dd 默认走页缓存,测出来的往往是内存速度。这一篇用标准工具 fio 在一台真实的 Ubuntu 24.04 云服务器上做完整基准:安装确认 → 顺序吞吐 → 随机 IOPS → 延迟百分位解读,全部命令实测,截图即真实输出。

安装 fio 并确认测试目标

fio 在 Ubuntu 官方源里就有,apt install fio 即可。装完先确认版本和测试对象——看清楚盘在哪、多大、挂载在哪,后面所有测试都指向同一块盘:

fio --version && lsblk -d -o NAME,SIZE,ROTA,MODEL -e 7,251 && df -h /root | tail -1

fio 版本与磁盘确认

三个信息一次看全:fio 3.36;系统盘是 40G 的 vda(ROTA=1,云盘普遍把自己标成可旋转属性);根分区 /dev/vda2 已用 59%。-e 7,251 把 loop 设备(主设备号 7)和 zram(主设备号 251)从列表里排除,只留真实的块设备。

认识 fio 的核心参数

fio 单条命令就能跑一次完整基准,所有行为都由参数控制。先过一遍最常用的这组:

参数作用本文取值
--name任务名,显示在报告开头seq-write / randread-4k
--rwIO 模式:read/write 顺序,randread/randwrite 随机按测试目的选
--bs单次 IO 的块大小,4K 贴近数据库与虚拟机负载,1M 贴近大文件拷贝4k / 1M
--size测试文件大小512M / 1G
--numjobs并发任务数1
--iodepth队列深度,同时在设备上挂起多少 IO32
--ioengineIO 引擎,libaio 是 Linux 原生异步 IOlibaio
--direct=1绕过页缓存,直接读写设备1(必加)
--runtime + --time_based固定跑满指定秒数,而不是把 size 跑完就停15
--group_reporting多任务结果合并成一份报告-
--filename测试目标文件/root/fio-test

其中 --direct=1--iodepth=32 是两个关键角色:前者保证测的是盘而不是内存,后者让 4K 随机测试能压出设备真实的 IOPS 上限——数据库和虚拟化场景正是靠队列深度吃饭的。

顺序读写:测吞吐量

顺序场景用 1M 大块 + 队列深度 32,模拟大文件拷贝、备份这类负载。先测顺序写:

fio --name=seq-write --rw=write --bs=1M --size=1G --numjobs=1 --iodepth=32 --ioengine=libaio --direct=1 --runtime=15 --time_based --group_reporting --filename=/root/fio-test

顺序写测试结果

报告开头一行就是核心结论:write: IOPS=113, BW=114MiB/s (119MB/s)——15 秒里实打实写了 1730MiB,折算 114 MiB/s。两个数字自洽:1M 块一次一个,113 次/秒 × 1MiB ≈ 114MiB/s。往下看 IO depths : 32=98.2%,说明队列深度 32 全程打满;末尾 util=96.36% 表示测试期间设备利用率 96% 以上,这块盘是被压满的,数字可信。

顺序读只需把 --rw 换成 read

fio --name=seq-read --rw=read --bs=1M --size=1G --numjobs=1 --iodepth=32 --ioengine=libaio --direct=1 --runtime=15 --time_based --group_reporting --filename=/root/fio-test

顺序读测试结果

read: IOPS=112, BW=112MiB/s (118MB/s),与写基本持平(差 2%,属正常波动)。顺序吞吐这块盘就稳定在 112~114 MiB/s 一档。

4K 随机读写:测 IOPS

数据库、虚拟机磁盘的读写是大量 4K 小 IO 随机落盘,这才是云盘性能的真正分水岭。块大小换成 4k,文件缩到 512M,模式换 randread

fio --name=randread-4k --rw=randread --bs=4k --size=512M --numjobs=1 --iodepth=32 --ioengine=libaio --direct=1 --runtime=15 --time_based --group_reporting --filename=/root/fio-test

4K 随机读测试结果

read: IOPS=2272, BW=9090KiB/s (9308kB/s)——块从 1M 缩到 4K 后,IOPS 从 113 涨到 2272,但绝对带宽掉到 9MB/s 左右。这就是存储系统「IOPS 与带宽不可兼得」的直观体现:同样一秒的传输能力,切成 4K 小块就要一个一个排队处理。IO depths : 32=99.9%util=97.94% 说明队列和设备都被压满,2272 IOPS 就是这块盘在这组参数下的真实上限。

随机写同理,把 --rw 换成 randwrite

fio --name=randwrite-4k --rw=randwrite --bs=4k --size=512M --numjobs=1 --iodepth=32 --ioengine=libaio --direct=1 --runtime=15 --time_based --group_reporting --filename=/root/fio-test

4K 随机写测试结果

write: IOPS=2229, BW=8920KiB/s (9134kB/s),与随机读几乎一致。读写都在 2200~2300 IOPS 一档,这就是普通云盘的典型水平。

读懂延迟报告:slat、clat 与百分位

fio 报告里最值得琢磨的是延迟部分。以随机读为例,它分三层:

  • slat(submission latency):内核把 IO 提交出去花的准备时间,实测平均仅 4.9 微秒,可忽略;
  • clat(completion latency):IO 从提交到设备完成返回的时间,这才是应用真正「等」的部分;
  • lat:两者之和。

随机读的 clat (usec): avg=14074.33——平均 14.1ms。这个数和 IOPS 对得上:队列深度 32 ÷ 2272 IOPS ≈ 14.1ms,正好是利特尔法则(排队理论里 L=λW)的直接验证。iodepth 开得越大,单个 IO 平均延迟必然越高,因为大家都在排队——所以只看平均延迟谈快慢没有意义,要看队列在干嘛

更关键的是 clat percentiles 这组百分位:

  • 50th=10552 微秒 ≈ 10.6ms:一半请求在 10.6ms 内完成;
  • 99th=20579 ≈ 20.6ms:99% 的请求在 20.6ms 内完成;
  • 99.9th=24249 ≈ 24.2ms:最慢的千分之一也在 24.2ms 内。

注意分布的形状:1% 的请求不到 0.85ms,5% 在 1ms 左右,但 10% 分位直接跳到 10ms——最快的几个百分位和其余请求之间存在断崖。下面一行 lat (msec) : 2=1.74%, ..., 20=90.23%, 50=1.80% 更直白:90.23% 的请求延迟落在 10~20ms 区间。对数据库来说,平均 14ms 没什么感觉,但 P99 从 20ms 涨到 200ms,慢查询和锁等待就会成片出现——做容量评估时盯 99th 和 99.9th,而不是平均值

注意事项与常见坑

  1. --filename 的安全红线:永远指向一个测试文件(如 /root/fio-test),绝不写成 /dev/vda 这类整盘或分区设备——fio 对块设备是直接覆写,数据当场全毁。测完 rm /root/fio-test 释放空间。
  2. --direct=1 必加:不加的话读写全走页缓存,测到的是内存速度。dd 不加 oflag=direct 就是这个坑,很多「测试结果高得离谱」的帖子都栽在这里。
  3. 测试时长:本文 15 秒只为演示,正式评估建议 60 秒以上,并避开业务高峰——测试本身是重负载写入。
  4. 云盘结果会波动:云盘是多租户共享、按 QoS 限速的,同一命令多跑几轮数字会漂(本次顺序写采样里 bw 最小 61440、最大 245760 KiB/s,单次波动不小),评估时多跑几轮取区间,对比不同盘必须用完全相同的参数。
  5. 别拿本文数字当硬件上限:这是普通云盘的水平,本地 NVMe SSD 随机 4K 轻松几十万 IOPS,差两个数量级;选型时用同一套 fio 参数实测对比才有意义。

小结

一组命令四种模式,这台 40G 云盘的完整画像:

测试块大小IOPS带宽clat 平均P50P99设备利用率
顺序写1M113114 MiB/s272.93 ms292 ms439 ms96.4%
顺序读1M112112 MiB/s275.80 ms292 ms351 ms97.1%
随机读4K22729308 kB/s14.07 ms10.6 ms20.6 ms97.9%
随机写4K22299134 kB/s14.34 ms10.3 ms20.1 ms97.6%

读法很简单:顺序看带宽、随机看 IOPS、体感看 P99。下次买机器验盘、数据库选盘、或者排查「磁盘慢」时,用文里这套参数直接跑一轮,和基准一比就知道问题在盘还是在使用方式。

发表评论

暂无评论,快来抢沙发吧!