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

分类服务器标签
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-cli

Rocky / AlmaLinux / CentOS:

dnf install -y nvme-cli

二、查看磁盘剩余空间

如果要通过测试文件测试,首先确认挂载点有足够空间:

df -h

例如需要测试某个挂载目录:

df -h /data

测试文件不要超过该分区的可用空间。


三、安装 fio

Debian / Ubuntu

apt update && apt install -y fio

Rocky Linux / AlmaLinux / RHEL

dnf install -y fio

CentOS 7

yum install -y fio

查看版本:

fio --version

四、先理解两种测试方式

Linux 磁盘测试主要分两类。

方式一:测试文件

例如:

--filename=/data/fio_test

fio 会在已经挂载的文件系统里面创建测试文件。

优点:

不会格式化磁盘
不会直接覆盖整个分区
适合系统盘
适合正在使用的数据盘
风险相对较低

生产服务器通常推荐这种方式。


方式二:直接测试裸设备

例如:

--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_reporting

NVMe 高并发测试

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

建议先连续确认:

lsblk
fdisk -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_reporting

4K 随机:

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

可以辅助判断磁盘是否已经处于高负载。


二十九、推荐的标准测试组合

如果只是服务器验机,我通常建议至少跑以下几个项目:

测试项目

参数

主要用途

顺序读

1M QD32

大文件读取

顺序写

1M QD32

大文件写入

4K 随机读

QD1

低延迟能力

4K 随机读

QD32

并发 IOPS

4K 随机写

QD32

写 IOPS

4K 70/30

QD32

综合业务负载

持续写

60~300秒

缓存耗尽后性能

这样得到的数据比单纯执行一次:

dd

更有参考意义。


三十、总结

Linux 下测试 HDD、SSD、NVMe、SAS 和 RAID,推荐统一使用:

fio

如果磁盘中已经存在数据:

使用测试文件

如果是一块完全空的新盘:

可以进行裸设备测试

如果只是测试裸盘读取:

可以使用只读测试

如果需要测试真实存储性能,建议同时观察:

顺序读写
4K IOPS
QD1
QD32
混合读写
平均延迟
99% 延迟
持续性能

对于机械盘、SSD、NVMe 和 RAID,也不要使用同一个数字简单判断好坏,因为它们的设计目标和性能特点本身就不同。

日常服务器验机建议优先使用文件方式,不破坏现有分区和数据;只有确认目标设备为空盘时,才考虑直接针对 /dev/sdX/dev/nvmeXnY 进行写入测试。

本文为原创实践记录,首发于 小航博客,转载请注明出处与链接。

评论

发表评论

评论经审核后显示。请勿提交广告或与主题无关的内容。