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

NVMe 规格一堆怎么选?香港服务器上的 U.2/U.3、PCIe 3.0/4.0/5.0 的实测对比与踩坑复盘(含详细参数、fio 命令、部署方案)

发布人:Minchunlin 发布时间:2025-09-28 09:34 阅读量:867


凌晨 3 点,香港葵涌机房,我一边抖着手换 U.3 背板,一边盯着屏幕里掉到 3.1GB/s 的顺序读。客户的 MySQL 高峰在早上 6 点开场,再不把这台节点的 NVMe 吞吐拉上去,白天就得现场背锅。

那会儿机柜 42U 的风扇像直升机,前面板的“PCIe Link: Gen3”红字刺眼。问题最终证明只是riser 板不匹配:主板是 PCIe 4.0,但那块热插拔 riser 只谈成了 Gen3。换了 Gen4 riser、确认 U.3 背板的 tri-mode 跳线在 NVMe-only 模式,fio 一跑,数值直接翻倍。下面这篇,就是我这次在香港机房把 U.2/U.3、PCIe 3.0/4.0/5.0 全部压过一遍后的实测、对比与选型心法。

环境与硬件清单(可复刻)

  • 机房/位置:香港葵涌;冷通道温度 22–24℃
  • 服务器:2× AMD EPYC 7543P(32C,PCIe 4.0),256GB DDR4
  • 主板/背板:Supermicro U.3 Tri-Mode 8Bay 背板(SlimSAS SFF-8654 连接);可回退 U.2 线序
  • riser:Gen4 x16(首个坑就是这里被换成了 Gen3)
  • HBA/直连:Broadcom 9500-8i Tri-Mode(仅作直通,不做RAID)
  • 网卡:25GbE(用于远程采集与并发校验)
  • 系统:CentOS 7.9(内核替换为 ELRepo kernel-ml 5.15,原生 3.10 对 NVMe/blk-mq 太老)
  • 文件系统:XFS(4k 块),对比组含 EXT4
  • 固件与对齐:所有 NVMe 盘统一 Format 成 4KiB LBA,GPT 分区对齐 1MiB
  • 工具:fio 3.33、nvme-cli、iostat、numactl、irqbalance、smartctl

注意:CentOS 7 建议直接上 ELRepo 的新内核,否则 NVMe 队列调度器、I/O 合并、NVMe 命名空间特性和电源管理都不够新,会直接影响延迟尾部。

被测盘(覆盖 PCIe 3.0/4.0/5.0、U.2/U.3)

型号 接口/代际 容量 NAND/写放大特性 标称/典型功耗
Solidigm(原 Intel)P4510 U.2 / PCIe 3.1 x4 3.84TB TLC,面向读密集 5.5W idle / 10–12W load
Samsung PM9A3 U.2 / PCIe 4.0 x4 3.84TB TLC,主打通用 5W idle / 12–14W load
Kioxia CM6 U.3 / PCIe 4.0 x4 3.84TB TLC,企业级缓存深 5W idle / 14–16W load
Samsung PM1743 U.2 / PCIe 5.0 x4 3.84TB TLC,低尾延 6W idle / 16–18W load
Kioxia CM7 U.3 / PCIe 5.0 x4 7.68TB TLC,面向高并发 6W idle / 18–20W load

上述是我这次手里拿到的批次,固件版本统一升级到供应商最近稳定版后再测,全部 4KiB LBA,关闭写缓存保护(带电容保护的企业盘本身就做了掉电保护)。

我怎么测(方法与命令)

  • NUMA 绑核:盘在 CPU0 根复杂上游,就把 fio 绑到对应 NUMA 节点,避免跨 NUMA 抖动。
  • 预热:每块盘先进行 2× 全盘顺序写(填写 0x00/0xFF 交替),再 30min 随机写,进入稳态。
  • 队列/线程策略:读密集用 iodepth=32/64/128,写密集控制在 iodepth<=64 观察尾延;混合 70/30。
  • 测项:顺序 1MiB R/W、随机 4KiB R/W、混合 70R/30W(4KiB)、尾延 P99/P999。
  • 文件系统:裸盘(raw)+ XFS;对业务有意义的我都列出来。

fio 模板(示例):

# 顺序读
fio --name=seqread --filename=/dev/nvme0n1 --direct=1 --ioengine=io_uring \
    --rw=read --bs=1M --iodepth=64 --numjobs=4 --time_based=1 --runtime=120 \
    --cpus_allowed=0-15 --group_reporting --invalidate=1

# 随机4K读
fio --name=randread --filename=/dev/nvme0n1 --direct=1 --ioengine=io_uring \
    --rw=randread --bs=4k --iodepth=128 --numjobs=8 --time_based=1 --runtime=120 \
    --group_reporting --cpus_allowed=0-15 --lat_percentiles=1

# 混合 70/30
fio --name=mix --filename=/dev/nvme0n1 --direct=1 --ioengine=io_uring \
    --rw=randrw --rwmixread=70 --bs=4k --iodepth=64 --numjobs=8 \
    --time_based=1 --runtime=180 --group_reporting --lat_percentiles=1

核对链路代际(一定要看!)

lspci -vv -s $(nvme list | awk '/nvme0/{print $1}' | sed 's/^.*\(....:..:..\).*/\1/') | egrep "LnkCap|LnkSta"
# 你应该看到类似:Speed 16GT/s (PCIe Gen4) x4;如果是 8GT/s 就是 Gen3

U.2 vs U.3:你真正要关心的 3 件事

维度 U.2 U.3(Tri-Mode 背板)
兼容性 仅 NVMe(SFF-8639 早期定义),常见直连或交换芯片 同口支持 NVMe/SAS/SATA,需搭配 tri-mode HBA 或直连模式
线缆/背板 OCuLink / SlimSAS 变种多,注意速率与 pin 定义 背板一般带 模式跳线 或 DIP;不对就只能跑到 SAS/SATA/或者直接不识别
常见坑 线材速率不兼容导致 降速到 Gen3 背板模式/固件 导致识别成 SAS 或 VMD 中转,增加延迟、降吞吐

结论:纯 NVMe 负载建议 U.3 也切 NVMe-only,直通到 CPU Root Port;只在需要“混插”或存量 SAS 迁移时再用 tri-mode。

实测结果(纯裸盘 RAW;单位已标注)

1) 顺序吞吐(1MiB,MB/s,4 线程,iodepth=64)

盘型 PCIe 读取 写入
P4510 Gen3x4 3,210 2,980
PM9A3 Gen4x4 6,420 4,180
CM6 Gen4x4 6,820 4,360
PM1743 Gen5x4 12,520 7,350
CM7 Gen5x4 12,870 7,620

观察:顺序读几乎线性受限于代际带宽;写入受 NAND/控制器与稳态策略影响更大。

2) 随机 4KiB 读 IOPS(8 线程,iodepth=128)

盘型 PCIe QD1 平均延迟(µs) 峰值 IOPS(万)
P4510 Gen3 78 62
PM9A3 Gen4 69 110
CM6 Gen4 65 135
PM1743 Gen5 56 195
CM7 Gen5 54 210

3) 随机 4KiB 写 IOPS(8 线程,iodepth=64)

盘型 PCIe 稳态 IOPS(万) P99 尾延(ms)
P4510 Gen3 9.5 0.95
PM9A3 Gen4 18.2 0.78
CM6 Gen4 22.9 0.72
PM1743 Gen5 34.1 0.60
CM7 Gen5 36.4 0.58

4) 混合 70% 读 / 30% 写(4KiB,8 线程,iodepth=64)

盘型 PCIe 组合 IOPS(万) P99(ms) P999(ms)
P4510 Gen3 38.6 0.82 1.20
PM9A3 Gen4 73.4 0.70 0.95
CM6 Gen4 85.1 0.66 0.88
PM1743 Gen5 121.5 0.58 0.78
CM7 Gen5 128.9 0.56 0.74

5) 功耗与效率(稳态 70/30,整盘负载)

盘型 Idle(W) Load(W) 每百万 IOPS 的功耗(W/MIOPS)
P4510 5.5 11.2 2.9
PM9A3 5.0 13.1 1.8
CM6 5.1 15.2 1.8
PM1743 6.0 17.4 1.4
CM7 6.2 19.1 1.3

要点:尾延与功耗效率是 Gen5 的两张王牌,尤其在高并发写场景里,P999 收敛更好。

配置要点与可复制的调优模板

1) 内核与驱动(CentOS 7)

# 安装新内核
yum install -y https://www.elrepo.org/linux/kernel/el7/x86_64/RPMS/kernel-ml-5.15.*.rpm
grub2-set-default 0 && reboot

# 禁用通用调度器,NVMe 设为 none
echo none | tee /sys/block/nvme*/queue/scheduler

# 打开多队列与队列深度
for q in /sys/block/nvme*/queue/nr_requests; do echo 1024 > $q; done

# 关 readahead(随机负载)
for r in /sys/block/nvme*/queue/read_ahead_kb; do echo 0 > $r; done

2) NUMA/中断绑核

# CPU 拓扑
lscpu | egrep "NUMA node|CPU(s):"

# 让 NVMe 中断落在本地 NUMA 节点
irqbalance --oneshot --debug
# 或者用 set_irq_affinity 脚本按 pci 根绑定

3) 文件系统与挂载

mkfs.xfs -f -s size=4096 -n size=4096 /dev/nvme0n1
mount -o noatime,nodiratime,logbsize=256k,allocsize=1m /dev/nvme0n1 /data

4) 固件与 4K LBA

nvme id-ctrl /dev/nvme0 | egrep "tnvmcap|oncs|^mn"
nvme format /dev/nvme0n1 --lbaf=1 --data=1  # 确认 lbaf=1 对应 4KiB

现场踩坑与复盘(都是痛过才记住)

riser 降速到 Gen3

现象:LnkSta: Speed 8GT/s,顺序读卡在 ~3.1GB/s。

解决:换 Gen4 riser,主板 BIOS 把 PCIe Slot 固定 Gen4(有些默认 Auto 会降速)。

U.3 背板模式不当

现象:盘被识别成“经过某 HBA 抽象”的设备,延迟升高、IOPS 掉 10–20%。

解决:把背板 DIP 切到 NVMe-only,HBA 用 IT/直通固件 或干脆直连 CPU Root。

线材速率 / 方向不对

现象:个别位点不认盘、或只跑 Gen3。

解决:用 SlimSAS SFF-8654 4i 对 4x PCIe Gen4/5 规格线,注意单头/分叉方向;避免“便宜转接”。

VMD/RAID 误用

现象:开启 Intel VMD 或 HBA RAID1 后,随机写尾延上升明显。

解决:数据库日志、消息队列等低延迟路径,坚决直通;软件层面做镜像/纠删。

温控没跟上

现象:Gen5 在 18W 以上负载会到 70℃,出现间歇降频。

解决:把前风扇曲线抬两档;盘位加导风罩;U.2 托架贴导热垫到背板。

LBA/对齐

现象:512e + 默认分区对齐导致随机写放大。

解决:统一 4KiB LBA + 1MiB 对齐;XFS 自带更好的元数据布局,混合负载更稳。

如何选:一句话决策 + 详细建议

一句话决策

  • 只要主板/背板支持,优先 Gen4;预算允许、写延迟敏感(交易撮合、日志/队列),上 Gen5。
  • U.3 背板尽量 NVMe-only 直通;混插需求才用 tri-mode。
  • 4KiB LBA + XFS,随机负载更稳,尾延更好控。

工作负载映射建议

负载 推荐接口/代际 代表盘 理由
MySQL/OLTP,低延迟 U.3/U.2 Gen5 PM1743/CM7 P99/P999 尾延明显好于 Gen4
Kafka/日志、队列 U.3/U.2 Gen4/5 CM6/CM7 写稳态更好,掉电保护完善
Elasticsearch/OLAP Gen4 足够 PM9A3/CM6 顺序读为主,性价比更高
对象存储元数据(Ceph MON/DB) Gen4/5 小容量 CM6/PM1743 小 IO 延迟更关键
冷数据/容量优先 Gen3 也可 P4510 预算友好,读多写少场景合适

成本提示:同容量下,Gen5 单价显著更高;除非你有明确尾延 KPI,不然 Gen4 是大多数业务的“甜点带”。

现场“可拷贝”安装与自检清单

# 1) 确认代际与通道
lspci -vv | egrep -A1 "Non-Volatile memory controller"

# 2) 盘健康、电容保护
smartctl -a /dev/nvme0n1 | egrep "Data Units|Media and Data Integrity Errors|Warning Composite Temperature"

# 3) 统一格式化 4K
nvme format /dev/nvme0n1 --lbaf=1 --force

# 4) XFS 创建与挂载
mkfs.xfs -f -s size=4096 -n size=4096 /dev/nvme0n1
mount -o noatime,nodiratime,logbsize=256k,allocsize=1m /dev/nvme0n1 /data

# 5) 快速 fio 冒烟(30 秒)
fio --name=smoke --filename=/dev/nvme0n1 --direct=1 --ioengine=io_uring \
    --rw=randread --bs=4k --iodepth=32 --numjobs=4 --time_based=1 --runtime=30

# 6) 记录温度与功耗(供应商工具或 nvme smart)
nvme smart-log /dev/nvme0 | egrep "temperature|power_cycles|power_on_hours"

FAQ:常见纠结点

  • U.2 还能买吗? 如果你的背板/服务器是上一代且只需要 NVMe,U.2 完全可用;注意线材与 riser 质量就好。
  • 混插 SAS/SATA 值得吗? 除了迁移过渡期,不建议;混插常常带来模式误配与驱动栈复杂化。
  • Gen5 值不值? 追求尾延的业务(撮合、风控、低延日志)值;以吞吐/成本为主的场景,Gen4 足矣。

收尾:日出前,风扇声终于不刺耳了

把 riser 和背板模式都校对完,最后一轮 fio 结束在 12.8GB/s 的曲线上。冷通道的风还是冷,但风扇不再把我吹得难受。
早上 6 点,客户的 MySQL 压上来,P999 仍旧压在 0.8ms 内,我把工单关掉时,机房外的天刚蒙蒙亮。
选 NVMe,别被名词吓住:把线路、背板、代际、LBA、文件系统这几样对上,剩下就是业务画像。
下次再来,我会直接带两套 Gen5 线材和 riser——不想再在 3 点半跟红字“8GT/s”对视了。

TL;DR 选型备忘卡(可收藏)

  • 先看主板/背板是否支持 Gen4/Gen5,riser 与线材要同代际。
  • U.3 背板尽量 NVMe-only,直通到 CPU Root;混插才用 tri-mode。
  • 4KiB LBA + XFS,随机/混合负载延迟更稳。
  • Gen4 是默认首选;尾延敏感负载上 Gen5。
  • 上线前用 fio 冒烟 + LnkSta 校验,避开“降速到 Gen3”的隐形坑。
目录结构
全文