Skip to content

NVMe 架构详解

NVMe 协议演进

存储协议演进历史:

IDE/PATA(1986)→ SATA(2003)→ SAS(2004)→ NVMe(2011)

关键突破:
  SATA/SAS:基于 SCSI 命令集,为 HDD 设计,队列深度有限
  NVMe:专为 Flash 设计,充分发挥 SSD 并行性

NVMe 技术优势

命令队列对比

SATA:
  1 个命令队列
  队列深度:32
  
SAS:
  1 个命令队列
  队列深度:254

NVMe:
  65535 个命令队列
  每队列深度:65535
  总并发命令:65535 × 65535 ≈ 43 亿
  
实际意义:
  NVMe SSD 内部有数千个 Flash 芯片并行工作
  NVMe 的多队列设计充分利用这种并行性
  SATA/SAS 的单队列成为瓶颈

CPU 开销对比

SATA/SAS I/O 路径:
  应用 → 系统调用 → VFS → 块层 → SCSI 层 → 驱动 → 控制器
  CPU 中断次数:每次 I/O 1 次中断

NVMe I/O 路径:
  应用 → 系统调用 → VFS → 块层 → NVMe 驱动 → 控制器
  CPU 中断次数:可批量处理(Interrupt Coalescing)
  
CPU 开销降低:约 50%(相比 SATA)

NVMe SSD 内部架构

NVMe SSD 内部结构:

NVMe 控制器
    ├── 主机接口(PCIe 4.0 x4)
    ├── Flash 控制器
    │   ├── ECC 引擎(纠错)
    │   ├── 磨损均衡(Wear Leveling)
    │   └── 垃圾回收(Garbage Collection)
    └── Flash 存储阵列
        ├── Die 0(并行单元)
        ├── Die 1
        ├── ...
        └── Die N(通常 8-32 个 Die)

Flash 类型:
  SLC(1 bit/cell):最快,最耐用,最贵
  MLC(2 bit/cell):平衡
  TLC(3 bit/cell):主流,性价比高
  QLC(4 bit/cell):最便宜,耐用性较低

NVMe-oF 网络存储

协议栈

NVMe-oF 协议栈:

主机端:
  应用

  NVMe 驱动(内核)

  NVMe-oF 传输层
    ├── NVMe/FC(FC 网络)
    ├── NVMe/RoCE(以太网 RDMA)
    └── NVMe/TCP(普通以太网)

存储端:
  NVMe-oF Target

  NVMe SSD(本地)

NVMe/TCP 配置

bash
# 主机端配置(Initiator)
# 加载 NVMe/TCP 模块
modprobe nvme-tcp

# 发现目标(Discovery)
nvme discover -t tcp -a <storage-ip> -s 4420

# 连接到 NVMe 子系统
nvme connect -t tcp \
    -a <storage-ip> \
    -s 4420 \
    -n nqn.2024-01.com.h3c:storage01

# 查看连接的 NVMe 设备
nvme list
nvme list-subsys

# 存储端配置(Target)
# 加载 NVMe/TCP target 模块
modprobe nvmet
modprobe nvmet-tcp

# 创建子系统
mkdir /sys/kernel/config/nvmet/subsystems/nqn.2024-01.com.h3c:storage01
echo 1 > /sys/kernel/config/nvmet/subsystems/nqn.2024-01.com.h3c:storage01/attr_allow_any_host

# 创建命名空间(关联 NVMe 设备)
mkdir /sys/kernel/config/nvmet/subsystems/nqn.2024-01.com.h3c:storage01/namespaces/1
echo /dev/nvme0n1 > /sys/kernel/config/nvmet/subsystems/nqn.2024-01.com.h3c:storage01/namespaces/1/device_path
echo 1 > /sys/kernel/config/nvmet/subsystems/nqn.2024-01.com.h3c:storage01/namespaces/1/enable

# 创建端口
mkdir /sys/kernel/config/nvmet/ports/1
echo tcp > /sys/kernel/config/nvmet/ports/1/addr_trtype
echo <storage-ip> > /sys/kernel/config/nvmet/ports/1/addr_traddr
echo 4420 > /sys/kernel/config/nvmet/ports/1/addr_trsvcid
echo ipv4 > /sys/kernel/config/nvmet/ports/1/addr_adrfam

# 关联子系统到端口
ln -s /sys/kernel/config/nvmet/subsystems/nqn.2024-01.com.h3c:storage01 \
    /sys/kernel/config/nvmet/ports/1/subsystems/

性能调优

bash
# NVMe SSD 性能调优

# 1. I/O 调度器(NVMe 推荐 none)
echo none > /sys/block/nvme0n1/queue/scheduler

# 2. 队列深度
cat /sys/block/nvme0n1/queue/nr_requests  # 查看当前值
echo 1024 > /sys/block/nvme0n1/queue/nr_requests

# 3. 预读(顺序读场景增大,随机读场景减小)
echo 0 > /sys/block/nvme0n1/queue/read_ahead_kb  # 随机读
echo 4096 > /sys/block/nvme0n1/queue/read_ahead_kb  # 顺序读

# 4. 文件系统挂载选项(XFS 推荐)
mount -o noatime,nodiratime,discard /dev/nvme0n1 /data
# noatime:不更新访问时间(减少写入)
# discard:启用 TRIM(维护 SSD 性能)

# 5. 性能测试
fio --name=nvme-test \
    --ioengine=io_uring \  # 最新高性能 I/O 引擎
    --iodepth=256 \
    --rw=randread \
    --bs=4k \
    --direct=1 \
    --size=100G \
    --numjobs=8 \
    --runtime=60 \
    --group_reporting \
    --filename=/dev/nvme0n1

褚成志的云与计算笔记