本文要点
- 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 3.36;系统盘是 40G 的 vda(ROTA=1,云盘普遍把自己标成可旋转属性);根分区 /dev/vda2 已用 59%。-e 7,251 把 loop 设备(主设备号 7)和 zram(主设备号 251)从列表里排除,只留真实的块设备。
认识 fio 的核心参数
fio 单条命令就能跑一次完整基准,所有行为都由参数控制。先过一遍最常用的这组:
| 参数 | 作用 | 本文取值 |
|---|---|---|
--name | 任务名,显示在报告开头 | seq-write / randread-4k |
--rw | IO 模式:read/write 顺序,randread/randwrite 随机 | 按测试目的选 |
--bs | 单次 IO 的块大小,4K 贴近数据库与虚拟机负载,1M 贴近大文件拷贝 | 4k / 1M |
--size | 测试文件大小 | 512M / 1G |
--numjobs | 并发任务数 | 1 |
--iodepth | 队列深度,同时在设备上挂起多少 IO | 32 |
--ioengine | IO 引擎,libaio 是 Linux 原生异步 IO | libaio |
--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
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
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,而不是平均值。
注意事项与常见坑
--filename的安全红线:永远指向一个测试文件(如/root/fio-test),绝不写成/dev/vda这类整盘或分区设备——fio 对块设备是直接覆写,数据当场全毁。测完rm /root/fio-test释放空间。--direct=1必加:不加的话读写全走页缓存,测到的是内存速度。dd 不加oflag=direct就是这个坑,很多「测试结果高得离谱」的帖子都栽在这里。- 测试时长:本文 15 秒只为演示,正式评估建议 60 秒以上,并避开业务高峰——测试本身是重负载写入。
- 云盘结果会波动:云盘是多租户共享、按 QoS 限速的,同一命令多跑几轮数字会漂(本次顺序写采样里 bw 最小 61440、最大 245760 KiB/s,单次波动不小),评估时多跑几轮取区间,对比不同盘必须用完全相同的参数。
- 别拿本文数字当硬件上限:这是普通云盘的水平,本地 NVMe SSD 随机 4K 轻松几十万 IOPS,差两个数量级;选型时用同一套 fio 参数实测对比才有意义。
小结
一组命令四种模式,这台 40G 云盘的完整画像:
| 测试 | 块大小 | IOPS | 带宽 | clat 平均 | P50 | P99 | 设备利用率 |
|---|---|---|---|---|---|---|---|
| 顺序写 | 1M | 113 | 114 MiB/s | 272.93 ms | 292 ms | 439 ms | 96.4% |
| 顺序读 | 1M | 112 | 112 MiB/s | 275.80 ms | 292 ms | 351 ms | 97.1% |
| 随机读 | 4K | 2272 | 9308 kB/s | 14.07 ms | 10.6 ms | 20.6 ms | 97.9% |
| 随机写 | 4K | 2229 | 9134 kB/s | 14.34 ms | 10.3 ms | 20.1 ms | 97.6% |
读法很简单:顺序看带宽、随机看 IOPS、体感看 P99。下次买机器验盘、数据库选盘、或者排查「磁盘慢」时,用文里这套参数直接跑一轮,和基准一比就知道问题在盘还是在使用方式。
评论 (0)
暂无评论,快来抢沙发吧!