Linux 硬盘性能测试完整教程:HDD、SSD、NVMe、RAID 通用

摘要
本文介绍 Linux 下使用 fio 测试 HDD、SATA/SAS SSD、NVMe、RAID 的方法,覆盖系统盘、挂载数据盘和空盘,并区分安全测试与破坏性测试。
前言
大家好,我是云核筑梦家。
服务器上常见的存储设备包括机械硬盘、SATA SSD、SAS SSD、NVMe SSD,以及由 RAID 卡组成的 RAID 阵列。
想知道一块盘实际性能怎么样,通常需要关注:
顺序读取速度
顺序写入速度
4K 随机读取 IOPS
4K 随机写入 IOPS
混合随机读写
IO 延迟Linux 下推荐使用:
fio本教程不针对某一台服务器,而是按照不同磁盘使用场景分别介绍测试方式。
一、测试前先识别磁盘
查看磁盘:
lsblk推荐使用更详细的格式:
lsblk -o NAME,SIZE,TYPE,FSTYPE,MOUNTPOINTS,ROTA,MODEL其中:
NAME 设备名称
SIZE 容量
TYPE disk / part / lvm 等
FSTYPE 文件系统
MOUNTPOINTS 挂载目录
ROTA 是否旋转磁盘
MODEL 硬盘型号ROTA 一般可以辅助判断:
ROTA=1 通常为机械硬盘
ROTA=0 通常为 SSD / NVMe查看 NVMe:
nvme list如果提示没有命令:
Debian / Ubuntu:
apt update && apt install -y nvme-cliRocky / AlmaLinux / CentOS:
dnf install -y nvme-cli二、查看磁盘剩余空间
如果要通过测试文件测试,首先确认挂载点有足够空间:
df -h例如需要测试某个挂载目录:
df -h /data测试文件不要超过该分区的可用空间。
三、安装 fio
Debian / Ubuntu
apt update && apt install -y fioRocky Linux / AlmaLinux / RHEL
dnf install -y fioCentOS 7
yum install -y fio查看版本:
fio --version四、先理解两种测试方式
Linux 磁盘测试主要分两类。
方式一:测试文件
例如:
--filename=/data/fio_testfio 会在已经挂载的文件系统里面创建测试文件。
优点:
不会格式化磁盘
不会直接覆盖整个分区
适合系统盘
适合正在使用的数据盘
风险相对较低生产服务器通常推荐这种方式。
方式二:直接测试裸设备
例如:
--filename=/dev/sdb直接针对整块物理盘进行测试。
这种方式可以减少文件系统的影响,更接近底层磁盘性能。
但需要特别注意:
对
/dev/sdb执行 fio 写入、随机写入或混合读写,会覆盖磁盘现有数据。
因此裸盘写测试只适合:
新盘
空盘
准备格式化的磁盘
确定没有任何重要数据的设备如果磁盘已经有系统、分区、数据库或者其他数据,不要使用裸盘写测试。
五、通用安全测试:已挂载磁盘
这是最常用的方法。
假设需要测试的磁盘挂载目录为:
/data首先设置测试文件:
/data/fio_test可以根据实际挂载目录修改。
六、顺序写入测试
主要测试大文件持续写入性能。
fio \
--name=seq_write \
--filename=/data/fio_test \
--size=10G \
--rw=write \
--bs=1M \
--direct=1 \
--ioengine=libaio \
--iodepth=32 \
--numjobs=1 \
--group_reporting重点看:
WRITE: bw=例如:
WRITE: bw=500MiB/s代表顺序写入大约:
500 MiB/s七、顺序读取测试
使用刚才创建的测试文件:
fio \
--name=seq_read \
--filename=/data/fio_test \
--size=10G \
--rw=read \
--bs=1M \
--direct=1 \
--ioengine=libaio \
--iodepth=32 \
--numjobs=1 \
--group_reporting重点看:
READ: bw=八、4K 随机读取测试
随机读取是判断数据库、虚拟机、小文件业务性能的重要指标。
fio \
--name=4k_randread \
--filename=/data/fio_test \
--size=10G \
--rw=randread \
--bs=4k \
--direct=1 \
--ioengine=libaio \
--iodepth=32 \
--numjobs=4 \
--runtime=60 \
--time_based \
--group_reporting重点看:
IOPS=
BW=
clat=九、4K 随机写入测试
fio \
--name=4k_randwrite \
--filename=/data/fio_test \
--size=10G \
--rw=randwrite \
--bs=4k \
--direct=1 \
--ioengine=libaio \
--iodepth=32 \
--numjobs=4 \
--runtime=60 \
--time_based \
--group_reporting随机写会产生较大的 SSD 写入量。
生产 SSD / NVMe 不建议长时间反复进行高强度随机写测试。
十、4K 70%读 + 30%写混合测试
这是比较常见的一种综合负载。
fio \
--name=4k_randrw \
--filename=/data/fio_test \
--size=10G \
--rw=randrw \
--rwmixread=70 \
--bs=4k \
--direct=1 \
--ioengine=libaio \
--iodepth=32 \
--numjobs=4 \
--runtime=60 \
--time_based \
--group_reporting表示:
70% 随机读取
30% 随机写入相比单独随机读或者随机写,更接近部分数据库、虚拟化和业务服务器的实际负载。
十一、已挂载磁盘一键综合测试
把:
/data换成实际磁盘挂载目录。
TEST_DIR=/data; TEST_SIZE=10G; \
fio --name=seq_write --filename=$TEST_DIR/fio_test --size=$TEST_SIZE --rw=write --bs=1M --direct=1 --ioengine=libaio --iodepth=32 --numjobs=1 --group_reporting && \
fio --name=seq_read --filename=$TEST_DIR/fio_test --size=$TEST_SIZE --rw=read --bs=1M --direct=1 --ioengine=libaio --iodepth=32 --numjobs=1 --group_reporting && \
fio --name=4k_randread --filename=$TEST_DIR/fio_test --size=$TEST_SIZE --rw=randread --bs=4k --direct=1 --ioengine=libaio --iodepth=32 --numjobs=4 --runtime=60 --time_based --group_reporting && \
fio --name=4k_randrw --filename=$TEST_DIR/fio_test --size=$TEST_SIZE --rw=randrw --rwmixread=70 --bs=4k --direct=1 --ioengine=libaio --iodepth=32 --numjobs=4 --runtime=60 --time_based --group_reporting; \
rm -f $TEST_DIR/fio_test测试内容依次为:
1M 顺序写
1M 顺序读
4K 随机读
4K 70%读 + 30%写
自动删除测试文件如果测试系统根分区,可以把:
TEST_DIR=/data修改为:
TEST_DIR=/root如果数据盘挂载在 /mnt/storage:
TEST_DIR=/mnt/storage也就是说,测试文件放在哪个挂载点,就主要测试哪个磁盘或存储卷。
十二、为什么使用 direct=1
测试命令中使用:
--direct=1表示尽量绕过 Linux 页缓存。
如果不开启这个参数,读取测试可能大量命中内存缓存,出现远高于硬盘真实能力的结果。
因此做磁盘性能测试时通常推荐:
--direct=1十三、为什么要指定 libaio
很多人直接写:
--iodepth=32但 fio 默认可能使用同步 IO 引擎。
如果看到:
ioengine=psync并出现:
queue depth will be capped at 1说明虽然设置:
iodepth=32实际上队列深度仍然只有:
QD1可以通过:
--ioengine=libaio让异步队列真正发挥作用。
现代 Linux 也可以测试:
--ioengine=io_uring例如:
fio \
--name=test \
--filename=/data/fio_test \
--size=10G \
--rw=randread \
--bs=4k \
--direct=1 \
--ioengine=io_uring \
--iodepth=32 \
--runtime=60 \
--time_based如果追求较好的 Linux 版本兼容性,使用:
libaio即可。
十四、HDD 机械硬盘应该怎么测
机械硬盘重点关注:
顺序读写
QD1 随机性能
延迟机械盘并不擅长高并发 4K 随机 IO。
建议顺序测试:
fio \
--name=hdd_seq \
--filename=/data/fio_test \
--size=10G \
--rw=read \
--bs=1M \
--direct=1 \
--ioengine=libaio \
--iodepth=8 \
--numjobs=1 \
--group_reporting随机测试建议不要一开始使用特别高的并发。
例如:
fio \
--name=hdd_4k \
--filename=/data/fio_test \
--size=10G \
--rw=randread \
--bs=4k \
--direct=1 \
--ioengine=libaio \
--iodepth=1 \
--numjobs=1 \
--runtime=60 \
--time_based \
--group_reporting这样比较容易观察机械盘自身的真实延迟。
十五、SATA SSD 怎么测
SATA SSD 的接口理论上限大约在:
SATA III 6Gbps实际优秀 SATA SSD 顺序读写通常不会超过 SATA 接口极限。
建议使用:
顺序:1M / QD32
随机:4K / QD32例如:
fio \
--name=sata_ssd \
--filename=/data/fio_test \
--size=20G \
--rw=randrw \
--rwmixread=70 \
--bs=4k \
--direct=1 \
--ioengine=libaio \
--iodepth=32 \
--numjobs=4 \
--runtime=60 \
--time_based \
--group_reporting十六、SAS SSD 怎么测
SAS SSD 的测试方法和 SATA SSD 类似。
但是企业级 SAS SSD 通常在:
持续性能
并发 IO
延迟稳定性
耐久度方面表现更好。
建议至少测试:
1M 顺序读取
1M 顺序写入
4K QD1
4K QD32
70/30 混合随机十七、NVMe SSD 怎么测
NVMe 最大特点是:
高队列深度
高 IOPS
低延迟
高吞吐因此 NVMe 不能只使用 QD1 测一下就下结论。
建议分别测试:
QD1
QD32
高并发NVMe 4K QD1
fio \
--name=nvme_qd1 \
--filename=/data/fio_test \
--size=20G \
--rw=randread \
--bs=4k \
--direct=1 \
--ioengine=libaio \
--iodepth=1 \
--numjobs=1 \
--runtime=60 \
--time_based \
--group_reporting这个测试主要看低队列深度延迟。
NVMe 4K QD32
fio \
--name=nvme_qd32 \
--filename=/data/fio_test \
--size=20G \
--rw=randread \
--bs=4k \
--direct=1 \
--ioengine=libaio \
--iodepth=32 \
--numjobs=1 \
--runtime=60 \
--time_based \
--group_reportingNVMe 高并发测试
fio \
--name=nvme_high_qd \
--filename=/data/fio_test \
--size=20G \
--rw=randrw \
--rwmixread=70 \
--bs=4k \
--direct=1 \
--ioengine=libaio \
--iodepth=32 \
--numjobs=4 \
--runtime=60 \
--time_based \
--group_reporting这里相当于多个任务同时提交 IO,可以更充分地压测 NVMe。
十八、RAID 阵列怎么测
硬件 RAID 在 Linux 中经常表现为:
/dev/sda即使底层可能存在:
4块
8块
12块
24块Linux 仍然只看到一个逻辑磁盘。
RAID 测试方法与普通磁盘类似。
如果 RAID 已经安装系统或者保存数据,推荐:
测试文件方式如果 RAID 是刚创建的空逻辑盘,并且确定没有数据,可以进行裸设备测试。
特别需要注意 RAID 卡的:
Write Back Cache
Read Ahead
磁盘 Cache
BBU / CacheVault
RAID Level
条带大小都会明显影响测试结果。
短时间顺序写测试很容易被 RAID 卡缓存影响。
因此 RAID 持续性能测试建议:
测试文件 ≥ RAID 卡缓存很多倍
持续时间 60 秒以上例如:
fio \
--name=raid_write \
--filename=/data/fio_test \
--size=50G \
--rw=write \
--bs=1M \
--direct=1 \
--ioengine=libaio \
--iodepth=32 \
--runtime=60 \
--time_based \
--group_reporting十九、空盘裸设备只读测试
如果只是想测试一块裸盘的读取性能,可以避免写入。
假设设备:
/dev/sdb先再次确认:
lsblk /dev/sdb顺序读取:
fio \
--name=raw_read \
--filename=/dev/sdb \
--readonly \
--rw=read \
--bs=1M \
--direct=1 \
--ioengine=libaio \
--iodepth=32 \
--runtime=60 \
--time_based \
--group_reporting随机读取:
fio \
--name=raw_randread \
--filename=/dev/sdb \
--readonly \
--rw=randread \
--bs=4k \
--direct=1 \
--ioengine=libaio \
--iodepth=32 \
--runtime=60 \
--time_based \
--group_reporting因为只有读取,不会主动覆盖磁盘内容。
二十、空盘裸设备破坏性测试
以下命令会覆盖目标磁盘数据。
只有在确定设备完全为空、数据可以全部丢弃时才可以执行。
假设测试:
/dev/sdb建议先连续确认:
lsblkfdisk -l /dev/sdb确认无误后才进行测试。
顺序写:
fio \
--name=raw_write \
--filename=/dev/sdb \
--rw=write \
--bs=1M \
--direct=1 \
--ioengine=libaio \
--iodepth=32 \
--runtime=60 \
--time_based \
--group_reporting4K 随机:
fio \
--name=raw_randrw \
--filename=/dev/sdb \
--rw=randrw \
--rwmixread=70 \
--bs=4k \
--direct=1 \
--ioengine=libaio \
--iodepth=32 \
--runtime=60 \
--time_based \
--group_reporting执行以后:
原有文件系统
分区内数据
文件都有可能损坏。
因此生产服务器除非测试全新空盘,否则不要使用裸盘写测试。
二十一、只想快速看读取速度
还可以使用:
hdparm -Tt /dev/sda如果没有:
apt install -y hdparm输出通常包含:
Timing cached reads
Timing buffered disk reads需要注意:
hdparm -T主要测试缓存/内存相关能力。
真正更值得关注的是:
hdparm -t它只能简单查看顺序读取,不能替代 fio。
二十二、使用 dd 快速测试写入
简单测试:
dd if=/dev/zero of=/data/testfile bs=1G count=10 oflag=direct status=progress测试完成:
rm -f /data/testfile读取:
dd if=/data/testfile of=/dev/null bs=1G iflag=direct status=progress不过 dd 主要只能看简单吞吐量。
如果需要:
IOPS
随机 IO
延迟
并发
队列深度
混合读写还是应该使用:
fio二十三、fio 结果怎么看
fio 最主要关注三个指标。
BW
BW即 Bandwidth,吞吐量。
例如:
BW=1000MiB/s代表大约:
1000 MiB/s主要用于判断:
顺序读取
顺序写入IOPS
IOPS表示每秒完成多少次 IO 操作。
例如:
IOPS=100k代表:
约 100000 次 IO / 秒主要用于判断:
4K 随机性能
数据库
虚拟机
高并发存储clat
clat表示完成延迟。
常见单位:
nsec
usec
msec换算关系:
1000 ns = 1 μs
1000 μs = 1 ms通常:
延迟越低越好但不能只看平均值。
还应该观察:
95%
99%
99.9%高百分位延迟,因为它们更容易暴露磁盘卡顿和尾延迟问题。
二十四、不同磁盘不要只比较 MB/s
很多人测试硬盘只看:
2000MB/s
3000MB/s
5000MB/s实际上顺序吞吐只是一个指标。
例如服务器用于:
数据库
PVE
VMware
Docker
大量虚拟机
大量小文件更应该关注:
4K IOPS
QD1 延迟
QD32 性能
99% 延迟
持续写入稳定性而备份服务器、大文件存储和视频存储通常更关注:
顺序读写吞吐因此没有一个单独的数字可以代表一块磁盘的全部性能。
二十五、测试文件应该设置多大
简单验机:
5G~10G普通 SSD / RAID:
20G~50G希望降低缓存影响:
50G~100G 或更大高性能企业 NVMe 测试持续性能时,可以根据磁盘容量和业务情况进一步增大。
原则是:
测试文件越小,越容易受到系统缓存、SSD SLC Cache、RAID Cache 等因素影响。
二十六、为什么第一次写很快,后面变慢
SSD 和 NVMe 经常存在:
SLC Cache短时间写入时可能非常快。
当缓存写满以后,速度可能明显下降。
因此想测试持续写入性能,可以:
fio \
--name=sustained_write \
--filename=/data/fio_test \
--size=100G \
--rw=write \
--bs=1M \
--direct=1 \
--ioengine=libaio \
--iodepth=32 \
--runtime=300 \
--time_based \
--group_reporting持续运行:
300 秒比几秒钟的测试更能反映长期写入表现。
二十七、生产环境测试注意事项
生产环境中 fio 会真实产生磁盘负载。
测试期间可能造成:
网站响应变慢
数据库延迟升高
虚拟机卡顿
IO Wait 上升
RAID 阵列负载升高
SSD 写入量增加因此推荐在业务低峰期进行。
尤其下面这种测试:
4K randwrite
4K randrw
多 Job
高 QD
持续几分钟会给存储系统带来很高压力。
二十八、测试时同时观察系统 IO
可以安装:
apt install -y sysstat然后:
iostat -x 1重点关注:
r/s
w/s
rkB/s
wkB/s
await
%util其中:
await代表 IO 平均等待时间。
%util可以辅助判断磁盘是否已经处于高负载。
二十九、推荐的标准测试组合
如果只是服务器验机,我通常建议至少跑以下几个项目:
这样得到的数据比单纯执行一次:
dd更有参考意义。
三十、总结
Linux 下测试 HDD、SSD、NVMe、SAS 和 RAID,推荐统一使用:
fio如果磁盘中已经存在数据:
使用测试文件如果是一块完全空的新盘:
可以进行裸设备测试如果只是测试裸盘读取:
可以使用只读测试如果需要测试真实存储性能,建议同时观察:
顺序读写
4K IOPS
QD1
QD32
混合读写
平均延迟
99% 延迟
持续性能对于机械盘、SSD、NVMe 和 RAID,也不要使用同一个数字简单判断好坏,因为它们的设计目标和性能特点本身就不同。
日常服务器验机建议优先使用文件方式,不破坏现有分区和数据;只有确认目标设备为空盘时,才考虑直接针对 /dev/sdX 或 /dev/nvmeXnY 进行写入测试。
评论