上一篇 下一篇 分享链接 返回 返回顶部

NVMe U.2全闪存标称百万IOPS,验收要看哪些指标?

发布人:Minchunlin 发布时间:2026-10-06 08:44 阅读量:7

“百万IOPS”不是一项脱离条件的固定能力。对美国服务器上的NVMe U.2全闪存交付,验收不能只看厂商页面或服务商截图,而要确认这组数字对应的是单块SSD、多个盘组成的阵列,还是文件系统与网络服务的综合结果;同时记录块大小、读写比例、队列深度、线程数、测试时长、延迟分位数和设备温度。

建议把验收分成五个层次:配置真实性、NVMe磁盘与PCIe链路、网络端口与路由、同口径性能测试、长时间稳定性。只有测试条件和交付配置能够一一对应,百万IOPS才具有决策价值。以下示例以Linux系统、专用测试卷和常见PCIe NVMe U.2设备为基础,具体通过标准应以合同或订单中的配置与性能条款为准。

一、先把“百万IOPS”变成可核对的指标

1. 明确被验收的对象

交付前应先写清楚测试对象,否则很容易出现“单盘规格”和“阵列结果”混用的情况。

验收对象需要确认的内容常见误区
单块NVMe U.2 SSD型号、容量、固件、PCIe代际、通道宽度、单盘IOPS用多盘阵列成绩代表单盘能力
多盘全闪存阵列盘数、RAID或软件存储方式、条带大小、校验策略、可用容量只报阵列总IOPS,不说明盘数和阵列类型
文件系统卷文件系统、挂载参数、加密、缓存策略、测试文件大小以裸设备成绩承诺应用层成绩
远程存储服务客户端位置、网络端口、路由、协议、并发连接数把本地盘IOPS当成远程访问IOPS
网络带宽端口协商速率、双向吞吐、丢包、重传、MTU用磁盘读写速度代替网络带宽

如果订单只写“NVMe U.2全闪存、百万IOPS”,验收时应要求补充至少以下条件:

  • IOPS是随机读、随机写,还是混合读写。
  • 块大小是4KiB、8KiB还是其他规格。
  • 队列深度和并发线程数是多少。
  • 测试的是单盘、整组磁盘、文件系统还是远程服务。
  • 测试持续时间、预热方式、稳态要求和延迟上限。
  • 是否包含网络传输、协议开销和客户端处理能力。
  • “百万”是平均IOPS,还是某个短时间峰值。

2. 理解IOPS、带宽和延迟的关系

IOPS和吞吐量不是同一个指标。计算时要先确认块大小和单位。

计算公式为:

吞吐量 = IOPS × 单次I/O大小

例如,1,000,000 IOPS使用4KiB块大小时:

  • 每秒传输量 = 1,000,000 × 4,096字节
  • 结果为4,096,000,000字节/秒
  • 按十进制换算约为4.096GB/s
  • 按二进制换算约为3.815GiB/s

如果块大小改为8KiB,同样的1,000,000 IOPS就需要约8.192GB/s的介质吞吐,可能已经接近或超过单条PCIe Gen4 x4链路的实际可用能力。因此,“百万IOPS”必须和块大小一起阅读。

网络带宽则通常使用bit/s。例如10Gbps链路的理论十进制传输能力为:

  • 10,000Mbps × 30秒 ÷ 8 ÷ 1000
  • 30秒内理论传输量约为37.5GB

实际测试中还会受到以太网、TCP、协议、CPU和接收端处理能力影响。磁盘测试显示4GB/s,并不代表10Gbps网络就一定能以同样速度传输;反过来,10Gbps端口也不能让单块低性能磁盘达到4GB/s。

延迟也不能被IOPS覆盖。一个示例是:队列深度为256、IOPS约为1,000,000时,用“队列深度 ÷ IOPS”估算平均在途时间约为256微秒,但这只是近似关系,并不能代替p99或p99.9延迟。高队列深度下得到的百万IOPS,可能伴随较高的尾延迟,不一定适合低延迟数据库或交易型业务。

二、按交付顺序核对配置真实性

1. 先固定主机、磁盘和网络清单

验收不要从跑测试开始。先建立一份交付清单,记录服务器主机名、IP、机房或区域标识、系统版本、CPU型号、内存、NVMe数量、每块盘的序列号、容量、固件和网络端口信息。

美国服务器的物理区域应以订单、服务商控制台或交付单中的机房信息为准,IP地理定位只能作为辅助信息,不能单独作为机房位置证据。公网IP段可能被注册在其他地区,BGP路由也可能经过不同网络。

在服务器上执行以下基础检查:

date -Is
hostnamectl
uname -a
lscpu
free -h
lsblk -d -o NAME,SIZE,MODEL,SERIAL,ROTA,TRAN,TYPE
sudo nvme list
ip -br addr
ip -br link

重点查看:

  • lsblk中的设备是否为nvme而不是SATA或虚拟块设备。
  • NVMe数量是否与订单一致。
  • 型号和容量是否与交付单一致。
  • 序列号是否逐块记录,避免替换盘后仍沿用旧截图。
  • 网络接口数量、接口名称和协商速率是否符合配置。
  • 是否存在云平台或虚拟化层,导致看到的是虚拟磁盘而非直通U.2设备。

如果容量使用TB和TiB两种口径,应单独记录。厂商通常以十进制TB标注,操作系统可能以GiB或TiB显示,不能仅凭显示数值差异判定缺盘。需要结合型号标称容量、分区表、阵列预留空间和文件系统可用容量判断。

2. 确认U.2端口真正连接到PCIe NVMe链路

U.2是物理连接形式,不自动等于完整PCIe x4性能。实际链路可能受到主板插槽、背板、转接卡、PCIe交换芯片、BIOS设置或通道共享影响。

查看NVMe控制器与PCIe设备的关系:

sudo nvme list-subsys
readlink -f /sys/class/nvme/nvme0/device
BDF=$(basename "$(readlink -f /sys/class/nvme/nvme0/device)")
lspci -s "$BDF" -vv
lspci -t

在lspci -vv中重点记录:

  • LnkCap:设备支持的最高链路速度和宽度。
  • LnkSta:当前实际协商的链路速度和宽度。
  • 是否显示PCIe错误、链路降级或设备异常。
  • 设备挂在哪个CPU或PCIe根端口下。
  • 是否经过PCIe交换芯片或重定时器。

常见链路标识的含义如下:

链路信息说明
16GT/s, Width x4通常对应PCIe Gen4 x4,具体仍需结合设备和主板信息
8GT/s, Width x4通常对应PCIe Gen3 x4
16GT/s, Width x2代际不一定低,但通道数减少,带宽和并发能力可能受影响
8GT/s, Width x1可能是插槽、背板、BIOS分配或硬件连接异常
当前协商速率低于支持能力需要检查BIOS、固件、背板、温度和链路错误

不要只看LnkCap。设备支持PCIe Gen4 x4,不代表当前一定以Gen4 x4运行;验收应以LnkSta的当前状态为准。

用通用U.2 SSD、简化背板和主机PCIe根端口构成概念连接示意,在SSD附近标注物理接口,在链路附近并列标注LnkCap和LnkSta的模拟状态,突出实际状

还需要确认磁盘和CPU是否位于同一个NUMA节点:

numactl -H
lscpu -e=CPU,NODE,SOCKET
cat /sys/block/nvme0n1/device/numa_node

如果NVMe挂在NUMA节点1,而fio线程和内存主要位于节点0,测试结果可能包含跨节点访问开销。多路CPU服务器应至少进行一次本地NUMA测试,并记录CPU绑定方式。否则不同测试人员在不同CPU节点启动相同命令,结果可能出现明显差异。

3. 检查磁盘健康状态和固件

执行健康检查:

sudo nvme smart-log /dev/nvme0
sudo nvme id-ctrl /dev/nvme0
sudo nvme id-ns /dev/nvme0n1

重点保存以下字段:

  • critical_warning
  • temperature
  • available_spare
  • percentage_used
  • data_units_read
  • data_units_written
  • media_errors
  • num_err_log_entries
  • 固件版本
  • 型号、序列号和容量

验收时不能只看“SMART正常”。如果存在介质错误、错误日志持续增长、可用备用空间异常下降或关键警告,应先停止性能判定,确认设备状态和更换责任。

健康数据要在测试前后各采集一次。对于长时间随机写,测试后的写入量、温度和错误计数可能明显变化。若只保存测试结束时的结果,就无法判断异常是交付时已存在,还是测试过程中产生。

固件版本也应纳入验收记录。相同型号的不同固件可能在功耗、温控、队列处理和稳定性方面存在差异。更换固件前要保留原始版本、当前健康数据和业务备份;固件升级失败可能导致设备不可用,不能在生产业务卷上未经审批执行。

三、检查端口、路由和网络带宽

本地NVMe性能与公网或专线网络性能是两组独立指标。服务器本地跑出百万IOPS,并不代表远程客户端能够获得相同结果。

1. 核对接口协商状态

先确认接口名称,再查看物理协商状态:

ip -br link
sudo ethtool ens160

将ens160替换为实际接口名称。重点记录:

  • Speed
  • Duplex
  • Auto-negotiation
  • Link detected
  • 接口错误和丢包计数
  • 网卡驱动和固件信息

如果订单为10Gbps,但ethtool显示1000Mb/s,需要先处理端口、模块、线缆、交换机端口或驱动问题,不能用磁盘测试结果掩盖链路降速。

可以保存接口统计:

sudo ethtool -S ens160
ip -s link show dev ens160

验收时应区分物理端口速率、TCP实际吞吐和应用有效吞吐。三者分别对应硬件链路、传输协议和业务程序,不应合并成一个“带宽值”。

2. 确认实际路由和MTU

从真实客户端向美国服务器发起测试,检查目的地址使用的源地址、网关和接口:

ip route get 203.0.113.20
tracepath -n 203.0.113.20
ping -c 20 203.0.113.20

将示例地址替换为实际测试端。ip route get可以确认本机选择的路由和出口接口;tracepath可辅助观察路径和MTU变化;ping只能反映ICMP探测结果,不能单独证明业务链路没有丢包,因为部分网络会限制或过滤ICMP。

如果服务通过固定网络、专线或内网访问,应从实际业务客户端测试,而不是只在服务器本机测试。公网路由可能因运营商、访问地区、时间段和目的IP不同而改变。

3. 用iperf3单独验证网络吞吐

iperf3主要在内存中生成和接收数据,适合将网络因素与磁盘因素分离。测试前应确认双方都有授权,并确保测试窗口不会影响其他业务。

服务端执行:

iperf3 -s

客户端执行正向和反向测试:

iperf3 -c 203.0.113.20 -P 4 -t 30 -O 5 -J > iperf3-forward.json
iperf3 -c 203.0.113.20 -P 4 -t 30 -O 5 -R -J > iperf3-reverse.json

参数含义:

  • -P 4使用4个并行流,避免单连接受窗口或CPU影响。
  • -t 30持续30秒,避免只记录瞬时峰值。
  • -O 5忽略前5秒预热阶段。
  • -R测试反向方向。
  • -J输出JSON,便于留档和复核。

结果需要同时查看带宽、重传、发送端和接收端速率。若正向正常、反向明显偏低,可能涉及交换机端口、路由策略、网卡队列或接收端处理能力。若iperf3正常而远程存储读写很低,应继续检查协议、客户端CPU、文件系统和存储服务,而不能直接判定NVMe故障。

四、建立可复现的NVMe性能测试

1. 测试前置条件

性能测试最好使用专用测试卷或专用目录。文件系统测试能够反映应用实际路径,但会包含文件系统、加密、挂载参数和阵列缓存开销;裸设备测试更接近设备本身,却会覆盖数据。

以下示例使用专用挂载点/mnt/nvme-test和测试文件,不直接写生产设备:

df -h /mnt/nvme-test
mkdir -p /mnt/nvme-test
fio --version

测试目录中的文件会被反复写入。使用前要确认该目录没有业务数据,并保留必要备份。不要把/dev/nvme0n1直接作为filename用于随机写,除非该命名空间已经确认为空、已完成备份、已得到变更批准,并且接受恢复或重新分区的影响。裸设备写入没有普通意义上的“撤销”,回滚通常只能依靠备份恢复或重新配置。

测试文件应足够大,避免系统页缓存影响结果。可按“至少大于内存容量的一部分、并明显大于业务工作集”的原则设置;资源有限时,64GiB可以作为示例起点,但不能对所有容量和内存配置一概而论。文件太小、测试时间太短或只跑一次,都可能得到不稳定的峰值。

开始前记录:

  • CPU和内存占用。
  • NVMe温度和健康计数。
  • 设备当前容量使用率。
  • 文件系统和挂载参数。
  • 测试文件大小。
  • fio版本、内核版本和ioengine。
  • 是否启用NUMA绑定。
  • 是否有备份任务、杀毒扫描、同步程序或其他I/O负载。

2. 随机读、随机写和混合读写

下面命令以4KiB随机读为例,测试文件只位于专用测试目录:

fio --name=randread-4k \
  --filename=/mnt/nvme-test/fio.bin \
  --size=64G \
  --rw=randread \
  --bs=4k \
  --ioengine=libaio \
  --direct=1 \
  --iodepth=64 \
  --numjobs=4 \
  --runtime=60 \
  --time_based \
  --ramp_time=10 \
  --group_reporting=1 \
  --norandommap=1 \
  --randrepeat=0 \
  --output-format=json \
  --output=/mnt/nvme-test/randread-4k.json

该配置的总在途深度大致为iodepth × numjobs,即256,但实际有效深度还会受内核、设备和fio版本影响。libaio在常见Linux环境中兼容性较好;如果系统和fio支持io_uring,也可以在保持其他条件不变的情况下单独进行对照测试,但必须记录ioengine变化,不能把两种结果直接合并。

随机写测试:

fio --name=randwrite-4k \
  --filename=/mnt/nvme-test/fio.bin \
  --size=64G \
  --rw=randwrite \
  --bs=4k \
  --ioengine=libaio \
  --direct=1 \
  --iodepth=64 \
  --numjobs=4 \
  --runtime=60 \
  --time_based \
  --ramp_time=10 \
  --group_reporting=1 \
  --norandommap=1 \
  --randrepeat=0 \
  --output-format=json \
  --output=/mnt/nvme-test/randwrite-4k.json

混合读写更接近一部分数据库、虚拟化和文件服务负载:

fio --name=randrw-4k-70read \
  --filename=/mnt/nvme-test/fio.bin \
  --size=64G \
  --rw=randrw \
  --rwmixread=70 \
  --bs=4k \
  --ioengine=libaio \
  --direct=1 \
  --iodepth=32 \
  --numjobs=4 \
  --runtime=60 \
  --time_based \
  --ramp_time=10 \
  --group_reporting=1 \
  --norandommap=1 \
  --randrepeat=0 \
  --output-format=json \
  --output=/mnt/nvme-test/randrw-4k-70read.json

随机写会改变设备内部状态,可能触发垃圾回收、磨损均衡和缓存回收。若先跑随机写、后跑随机读,应记录测试顺序,并在两项之间安排统一的空闲冷却时间。更换顺序后重新测试,结果可能不同。

3. 顺序带宽测试

顺序读写用于判断PCIe链路、阵列聚合和大块I/O能力,不能代替随机IOPS测试。

顺序读示例:

fio --name=seqread-1m \
  --filename=/mnt/nvme-test/fio.bin \
  --size=64G \
  --rw=read \
  --bs=1M \
  --ioengine=libaio \
  --direct=1 \
  --iodepth=32 \
  --numjobs=1 \
  --runtime=60 \
  --time_based \
  --ramp_time=10 \
  --group_reporting=1 \
  --output-format=json \
  --output=/mnt/nvme-test/seqread-1m.json

顺序写示例:

fio --name=seqwrite-1m \
  --filename=/mnt/nvme-test/fio.bin \
  --size=64G \
  --rw=write \
  --bs=1M \
  --ioengine=libaio \
  --direct=1 \
  --iodepth=32 \
  --numjobs=1 \
  --runtime=60 \
  --time_based \
  --ramp_time=10 \
  --group_reporting=1 \
  --output-format=json \
  --output=/mnt/nvme-test/seqwrite-1m.json

如果顺序带宽明显低于链路和设备的合理范围,先检查PCIe当前协商宽度、NUMA位置、阵列条带、文件系统空间和温度。不要因为随机读IOPS达标,就跳过顺序读写;备份、镜像、日志归档和大文件传输通常更依赖顺序带宽。

4. 长时间稳定性测试

60秒测试适合快速验收,不足以发现持续写入后的温度变化、SLC缓存耗尽或错误计数增长。需要验证稳定性的交付,建议在业务空闲窗口进行30分钟至数小时的重复测试,时间长度以合同要求和设备容量为准。

稳定性测试至少记录:

  • 每个时间段的IOPS和带宽。
  • 平均延迟、p95、p99、p99.9和最大延迟。
  • 每块NVMe的温度变化。
  • media_errors和错误日志数量。
  • CPU占用、软中断和I/O等待。
  • 网络测试中的重传和丢包。
  • 是否出现性能逐步下降或周期性抖动。

不能把“测试命令没有报错”作为稳定性的全部依据。设备可能没有返回I/O错误,但已经出现温度过高、尾延迟持续增加或吞吐周期性下降。

四、建立可复现的NVMe性能测试 / 长时间稳定性测试配图

五、用正确方法解释测试结果

1. 先看测试条件,再看数字

一个结果只有在条件完全一致时才具有可比性。至少需要同时查看:

  • rw:读、写或混合模式。
  • bs:块大小。
  • iodepth和numjobs:队列与并发。
  • runtime和ramp_time:持续时间与预热。
  • direct和文件系统路径。
  • 单盘还是阵列。
  • 测试前设备是否处于空闲、预热或稳态。
  • CPU、NUMA和网络位置。

以下是用于说明判读方式的模拟结果,不代表某一具体产品的实测成绩:

测试场景示例结果可作出的判断
单盘4KiB随机读,QD总计2561.03M IOPS,p99 420μs达到百万级随机读,但仍需确认高队列下的尾延迟
单盘4KiB随机写,QD总计2560.42M IOPS,p99 780μs不能用随机读标称值推断随机写能力
4KiB 70/30混合,QD总计1280.78M IOPS,p99 610μs更接近混合负载,不能称为“百万IOPS”
1MiB顺序读7.0GB/s需要结合PCIe代际、通道宽度和阵列盘数判断是否合理
1MiB顺序写,运行30分钟后下降前10分钟6.2GB/s,后续3.1GB/s可能涉及缓存耗尽、垃圾回收、温控或稳态差异

第一行结果可以描述为“在4KiB随机读、总队列深度约256的条件下达到百万级IOPS”。不能改写成“任何负载下均有百万IOPS”。

2. 关注尾延迟和异常计数

IOPS高但p99、p99.9延迟高,通常意味着设备依靠较深队列堆出吞吐。对于批处理、并行扫描等负载,这可能可以接受;对于数据库提交、虚拟机系统盘或实时服务,尾延迟往往比峰值IOPS更重要。

可以使用以下判断分支:

  • IOPS低、PCIe链路降为x1或x2:优先检查背板、转接卡、BIOS通道分配和物理连接。
  • 顺序带宽正常、随机IOPS低:检查块大小、队列深度、线程数、文件系统和设备固件。
  • 随机读达标、随机写明显低:确认产品写入规格、设备磨损状态、缓存策略和测试是否进入稳态。
  • 前几分钟很快、随后下降:观察温度、缓存耗尽和垃圾回收,不要只取前段峰值。
  • 平均延迟正常、p99.9异常:检查后台任务、NUMA跨节点、设备错误和网络抖动。
  • 本地fio正常、远程fio偏低:优先检查路由、端口、MTU、TCP重传、协议和客户端CPU。
  • 同配置重复结果差异大:先检查测试文件大小、冷却时间、后台负载和设备当前状态。

性能下限应尽量在合同中提前定义。例如,可以明确“4KiB随机读、指定队列深度和时长下,平均IOPS不低于某值,p99不高于某值,测试期间不得出现介质错误”。如果合同没有这些条件,验收记录应把本次测试条件写完整,避免后续把不同口径的数字放在一起比较。

3. 不把阵列、网络和单盘结果混为一谈

多块NVMe组成阵列后,IOPS可能随盘数增加,但阵列控制器、CPU、校验、条带大小和文件系统会带来额外开销。阵列结果还可能受最慢一块盘限制。

建议分别保存:

  1. 单块NVMe的设备级结果。
  2. 整组阵列或存储池的结果。
  3. 文件系统挂载路径的结果。
  4. 从实际客户端访问服务的结果。
  5. 独立iperf3网络结果。

如果交付条款只承诺整组全闪存的性能,就应把盘数、RAID级别、可用容量和测试路径写进验收单。如果条款承诺单盘性能,就不能用阵列总成绩替代。

六、出现异常时如何留证和定位

1. 保存原始命令和环境信息

截图适合辅助说明,不适合作为唯一证据。建议用终端录制和JSON结果保存完整过程:

mkdir -p "$HOME/acceptance-logs"
script -a "$HOME/acceptance-logs/session.log"
date -Is
hostnamectl
uname -a
fio --version
sudo nvme list
lsblk -d -o NAME,SIZE,MODEL,SERIAL,ROTA,TRAN,TYPE
ip -br addr
ip -br link

完成所有测试后执行:

exit
sha256sum "$HOME"/acceptance-logs/*
sha256sum /mnt/nvme-test/*.json

证据包应包含:

  • 订单或交付配置。
  • 主机名、IP和区域信息。
  • NVMe型号、序列号、容量和固件。
  • PCIe LnkCap、LnkSta和拓扑。
  • 测试前后的健康日志。
  • fio完整JSON或文本输出。
  • CPU、NUMA、系统版本和fio版本。
  • 网卡协商状态、路由和iperf3结果。
  • 测试开始结束时间、测试顺序和冷却时间。
  • 异常发生时的温度、错误计数和后台负载。

序列号和公网IP在公开发布时可以脱敏,但内部验收记录应保留完整值,以便追溯具体设备。

2. 异常时不要覆盖第一次结果

发现异常后,不要立即重启、更换固件、重新格式化或删除测试日志。先保存现场,再按影响范围进行复测:

  • 如果链路宽度不符,保留lspci -vv、主板或背板信息,要求服务商先核对硬件连接。
  • 如果健康计数异常,保存前后两次nvme smart-log,暂停高强度写入。
  • 如果温度升高后性能下降,记录温度曲线和每轮fio结果,再检查风道、风扇、散热片和温控策略。
  • 如果网络吞吐低,分别保存ethtool、ip route get、iperf3双向结果和客户端信息。
  • 如果只有文件系统路径异常,使用同一测试文件和参数对比专用卷、阵列卷或其他挂载点。
  • 如果只有某一块盘异常,不能用其他盘的平均值冲淡问题,应按序列号单独追踪。

七、复测时保持条件不变

复测不是重新运行一条命令这么简单。以下条件变化都可能改变结果:

  • PCIe代际或链路宽度。
  • 固件、BIOS、内核或fio版本。
  • 测试文件大小和文件系统。
  • ioengine、块大小、队列深度、线程数。
  • CPU亲和性和NUMA节点。
  • 测试顺序、预热时间和冷却时间。
  • 磁盘使用率、磨损程度和缓存状态。
  • 网络客户端、源地址、路由、MTU和并发连接数。
  • 是否存在备份、同步、监控扫描或其他I/O任务。

建议使用同一台客户端、同一块测试卷、同一组参数,在相同时间窗口完成复测。每项至少重复三次,并记录平均值、最好值、最差值和离散程度。若合同没有规定重复次数,可以把“同条件三次结果最大差异不超过约10%”作为内部复核参考,但不应把这个示例阈值当成所有设备的统一标准。

复测前后重新采集设备健康信息和链路状态。只有在“配置一致、链路正确、健康无异常、测试口径一致、性能达到约定下限、长时间运行无错误”的条件同时满足时,才适合在验收单上确认百万IOPS或其他性能指标。

最终留存的不是一张显示“1.0M IOPS”的截图,而是一套可复核的交付证据:设备身份对应哪块盘,当前PCIe端口是什么状态,测试使用了什么参数,结果包含多少IOPS、带宽和尾延迟,网络从哪个客户端经过什么路径,长时间运行是否出现降速或错误,以及异常后的复测是否仍能得到相同结论。