摘要:系统解析企业级SSD双端口(Dual Port)架构的硬件实现与协议原理,涵盖NVMe PCIe双端口与SAS双端口的拓扑差异、Active-Active/Active-Passive/ALUA三种路径访问模型、Asymmetric Namespace Access (ANA) 状态机转换、NVMe Multipath内核实现与I/O路径切换、RDMA/NVMe-oF双路径冗余、双端口SSD在HA双活存储阵列中的应用、以及fio多路径I/O性能与故障切换实测对比。
目录
- 一、为什么需要双端口:企业级存储的高可用需求
- 二、双端口SSD硬件架构:PCIe/SAS双控制器设计
- 三、双端口访问模型:Active-Active / Active-Passive / ALUA
- 四、NVMe ANA(Asymmetric Namespace Access)规范深度解读
- 五、SAS双端口与ALUA协议原理
- 六、Linux内核多路径子系统架构:DM-Multipath / nvme-multipath
- 七、NVMe Multipath 内核实现与I/O路径调度算法
- 八、故障切换机制与路径检测算法
- 九、双端口SSD在HA双活存储阵列中的应用
- 十、性能基准测试:单路径 vs 双路径 vs 多路径聚合
- 十一、双端口SSD的一致性与数据保护挑战
- 十二、当日知识点小结
- 十三、思考题
- 参考资料
一、为什么需要双端口:企业级存储的高可用需求
1.1 单点失效风险与99.999%可用性目标
企业级存储系统的核心设计目标是高可用性(High Availability),通常要求达到 99.999%(五个九)的可用性水平,即全年计划外停机时间不超过5.26分钟。
可用性计算公式:
可用性 = 正常运行时间 / (正常运行时间 + 停机时间) × 100%
| 可用性等级 | 年停机时间 | 月停机时间 |
|———–|———–|———–|
| 99% | 3.65天 | 7.31小时 |
| 99.9% | 8.76小时 | 43.8分钟 |
| 99.99% | 52.6分钟 | 4.38分钟 |
| 99.999% | 5.26分钟 | 26.3秒 |
| 99.9999% | 31.5秒 | 2.6秒 |
在传统直连存储(DAS)架构中,SSD通过单条PCIe链路连接到单台主机,存在多个单点故障(SPOF, Single Point of Failure):
主机侧单点故障链:
┌─────────┐ ┌──────────┐ ┌──────────┐ ┌──────┐
│ CPU/Root│────▶│ PCIe Switch│────▶│ NVMe SSD │────▶│ NAND │
│ Complex │ │ (单路径) │ │ (单端口) │ │ Flash │
└─────────┘ └──────────┘ └──────────┘ └──────┘
▲ ▲ ▲
│ │ │
└─ 单点失效 ─────┴─ 单点失效 ──────┘
双端口SSD的本质是在存储设备层消除单点故障,使同一块SSD能够同时连接到两台独立的主机控制器或存储控制器,从而在路径、控制器甚至整台主机故障时,数据访问仍能继续。
1.2 企业级存储的典型故障场景
根据SNIA(存储网络行业协会)的统计数据,企业级存储系统的故障分布如下:
| 路径/线缆故障 | ~35% | ✅ 完全防护 | HBA/PCIe卡、线缆、交换机端口故障 |
| 控制器故障 | ~25% | ✅ 可切换 | 存储控制器宕机、固件崩溃 |
| SSD介质故障 | ~20% | ❌ 需RAID | 双端口共享同一块NAND介质 |
| 电源故障 | ~12% | ⚠️ 部分防护 | 双电源+双端口可防护单电源故障 |
| 固件/软件故障 | ~8% | ✅ 可切换 | 单控制器固件hang住可切另一路径 |
关键认知:双端口SSD解决的是路径和控制器层面的高可用问题,而非介质层面的数据冗余。介质故障仍然需要依赖RAID、多副本或纠删码来保护。
1.3 双端口SSD的应用场景
双端口SSD的主要应用场景包括:
二、双端口SSD硬件架构:PCIe/SAS双控制器设计
2.1 双端口SSD的内部架构
双端口SSD与单端口SSD的核心区别在于前端接口层增加了一套独立的PHY和链路层,而NAND闪存介质是两个端口共享的。典型的双端口SSD内部架构如下:
双端口NVMe SSD内部架构(PCIe Dual Port)
Port A (PCIe x4) Port B (PCIe x4)
│ │
▼ ▼
┌──────────┐ ┌──────────┐
│ PCIe PHY │ │ PCIe PHY │
│ (Gen4) │ │ (Gen4) │
└────┬─────┘ └────┬─────┘
│ │
▼ ▼
┌────────────┐ ┌────────────┐
│ PCIe 控制器│ │ PCIe 控制器│
│ (Port A) │ │ (Port B) │
└─────┬──────┘ └──────┬─────┘
│ │
└───────────┬───────────┘
▼
┌─────────────────┐
│ 双端口主控芯片 │
│ (Shared FTL) │
│ – 仲裁引擎 │
│ – 缓存一致性 │
│ – 命名空间管理 │
└────────┬────────┘
▼
┌─────────────────┐
│ DRAM缓存 │
│ (共享LBA映射表) │
└────────┬────────┘
▼
┌─────────────────┐
│ NAND闪存阵列 │
│ (共享介质) │
└─────────────────┘
2.2 PCIe双端口的硬件实现方式
NVMe PCIe双端口SSD有两种主要的硬件实现方案:
方案一:双PCIe Root Complex集成(单芯片方案)
主流企业级主控芯片(如Samsung Phoenix、Marvell Bravera SC5、Phison PS5026-E26)内部集成了两个独立的PCIe控制器,共享同一个FTL核心和NAND通道:
单芯片双端口主控架构
┌──────────────────────────────────────────┐
│ 主控SoC │
│ │
│ ┌─────────┐ ┌─────────┐ │
│ │ PCIe RC │ │ PCIe RC │ ← 两个独立 │
│ │ Port A │ │ Port B │ PCIe端口 │
│ └────┬────┘ └────┬────┘ │
│ │ │ │
│ └──────┬───────┘ │
│ ▼ │
│ ┌──────────────────┐ │
│ │ FTL / MMU 核心 │ ← 共享FTL引擎 │
│ │ + 仲裁与互斥 │ │
│ └────────┬─────────┘ │
│ ▼ │
│ ┌──────────────────┐ │
│ │ NAND Flash 控制器│ │
│ └──────────────────┘ │
└──────────────────────────────────────────┘
方案二:PCIe Switch + 双主控(双芯片方案)
部分高端企业级SSD采用外置PCIe Switch+双主控芯片的架构,实现更彻底的硬件隔离:
| 硬件成本 | 较低 | 较高(2颗主控+Switch) |
| 故障隔离 | 单芯片故障影响两端口 | 单主控故障不影响另一主控 |
| 性能开销 | 共享总线存在竞争 | 并行度更高 |
| 典型产品 | 三星PM9A3、铠侠CD8 | 部分高端存储定制SSD |
| 固件复杂度 | 单固件镜像 | 双固件需同步 |
2.3 SAS双端口 vs PCIe双端口对比
企业级SSD的双端口技术路线主要分为SAS双端口和NVMe PCIe双端口两大阵营:
| 接口协议 | SAS 3.0 / 4.0(12G / 24G) | PCIe 4.0 / 5.0(16GT/s / 32GT/s) |
| 带宽/端口 | ~1.1 GB/s(12G SAS) | ~7.5 GB/s(PCIe 4.0 x4) |
| 双端口模式 | 天然支持(SAS标准定义) | NVMe 1.4+规范支持 |
| 访问模型 | ALUA标准 | ANA(NVMe定义) |
| 多路径软件 | DM-Multipath(SAS路径) | nvme-multipath(native) |
| 主要厂商 | 希捷、东芝、西部数据 | 三星、铠侠、美光、Solidigm |
| 应用场景 | 传统SAN存储、混闪阵列 | 全闪阵列、云数据中心、NVMe-oF |
行业趋势:根据IDC 2025年Q1报告,全球企业级SSD市场中,NVMe SSD的出货量占比已超过72%,PCIe双端口正在快速替代SAS双端口成为主流。但SAS双端口在传统企业存储市场仍有稳定存量,预计至少到2028年才会被全面替代。
2.4 双端口SSD的物理接口形式
双端口SSD常见的物理形态包括:
| 2.5寸 U.2 | SFF-8639 | PCIe双端口+SAS兼容 | 服务器、存储阵列 |
| E1.S | EDSFF E1 | 双x2 PCIe端口 | 云服务器、JBOF |
| E3.S | EDSFF E3 | 双x4 PCIe端口 | 全闪阵列、数据中心 |
| M.2 | M.2 | 通常单端口(部分双口) | 仅少数工业级 |
| U.3 | SFF-8639 v2 | 三模(SAS/SATA/NVMe)双端口 | 高端存储 |
U.2双端口引脚定义:SFF-8639连接器的Pin 1-36为Port A,Pin 37-68为Port B,两个端口各自拥有独立的PCIe收发差分对和参考时钟。
三、双端口访问模型:Active-Active / Active-Passive / ALUA
3.1 三种基本访问模型
双端口SSD根据两个端口对同一Namespace的访问权限和性能特性,分为三种基本模型:
访问模型对比
1. Active-Active(对称双活)
Port A ◄──── I/O ────► Namespace
Port B ◄──── I/O ────► Namespace
两端口性能一致,可同时读写
2. Active-Passive(主备)
Port A (Active) ◄── I/O ──► Namespace
Port B (Passive) Namespace
仅主端口可访问,备端口待机
3. ALUA/ANA(非对称访问)
Port A (Optimized) ◄══ I/O ══► Namespace 性能路径
Port B (Non-Optimized) ◄── I/O ──► Namespace 可用但性能低
3.2 Active-Active 对称双活模型
Active-Active(AA)模型下,两个端口都可以同时以最优性能访问同一个Namespace,主机可以通过两个端口并行发送I/O,实现负载均衡。
关键特性:
- 两端口对同一Namespace的访问延迟、带宽基本一致
- 支持I/O在两个端口间动态负载均衡
- 故障切换时无需等待路径状态切换,性能无跳变
- 实现复杂度最高,需要主控内部实现精细的缓存一致性
典型实现:
- 部分高端企业级NVMe SSD(如三星PM1743双端口版、铠侠CM7-R)
- 多数SAS双端口SSD在控制器端聚合后对主机呈现AA模式
3.3 Active-Passive 主备模型
Active-Passive(AP)模型下,同一时间只有一个端口(Active端口)可以访问Namespace,另一个端口(Passive端口)处于待机状态。当Active端口故障时,需要通过显式的路径切换将Passive端口提升为Active。
关键特性:
- 实现简单,硬件和固件成本低
- 正常工作时只有一条路径承载I/O
- 故障切换有延迟(通常10ms~数秒)
- 切换期间I/O会短暂挂起
切换流程:
Active-Passive 切换状态机
┌──────────────────────────────────┐
│ ▼
┌──────┐ 路径失效检测 ┌──────────────┐
│ Active│ ───────────────▶│ 切换准备 │
│ Port A │ 触发切换 │ (缓存刷新) │
└──────┘ └──────┬───────┘
│
▼
┌──────────────┐
│ Port B激活 │
│ (路径重建) │
└──────┬───────┘
│
▼
┌──────────────┐
│ I/O恢复 │
│ Port B Active│
└──────────────┘
3.4 ALUA/ANA 非对称访问模型
ALUA(Asymmetric Logical Unit Access,非对称逻辑单元访问)是一种介于Active-Active和Active-Passive之间的模型。SAS协议中称为ALUA,NVMe协议中对应的是ANA(Asymmetric Namespace Access)。
核心思想:两个端口都可以访问同一个LUN/Namespace,但通过不同端口访问的性能不同——一个是"优化路径"(Optimized),另一个是"非优化路径"(Non-Optimized)。
四种路径状态(NVMe ANA定义):
| ANA Optimized State | 优化状态 | ✅ 可访问 | 最优性能(直接路径) |
| ANA Non-Optimized State | 非优化状态 | ✅ 可访问 | 性能较低(需跨控制器转发) |
| ANA Inaccessible State | 不可访问状态 | ❌ 不可访问 | 路径故障或控制器离线 |
| ANA Change State | 转换中状态 | ⚠️ 临时不可用 | 状态正在切换中 |
NVMe 2.0规范新增状态:ANA Persistent Loss State(持久丢失状态),用于表示永久不可恢复的路径故障,主机应永久放弃该路径。
3.5 三种模型的对比总结
| 两端口同时访问 | ✅ 是 | ✅ 是(性能不对称) | ❌ 否 |
| 负载均衡 | ✅ 完全负载均衡 | ⚠️ 不均衡(优化路径为主) | ❌ 无负载均衡 |
| 故障切换延迟 | ~0ms(I/O自动走另一路径) | 低(直接切到非优化路径) | 较高(需显式激活) |
| 实现复杂度 | 最高 | 中等 | 最低 |
| 典型应用 | 高端全闪阵列 | 中端存储/双控阵列 | 入门级HA / 备份路径 |
| 性能利用率 | ~200%(双端口聚合) | 110%150% | ~100% |
四、NVMe ANA(Asymmetric Namespace Access)规范深度解读
4.1 ANA的规范定位
ANA是NVMe Base Specification 1.4引入的特性,在NVMe 2.0中得到进一步增强。它是NVMe对多路径访问标准化的核心机制,替代了早期厂商私有的多路径方案。
NVMe 2.0 RMT-39 规范定义:ANA (Asymmetric Namespace Access) 是一种报告命名空间访问特性的机制,这些特性可能因控制器和端口的不同而有所差异。ANA使主机软件能够优化I/O路径选择,在保持对所有路径访问能力的同时,优先使用最优性能路径。
4.2 ANA日志页(ANA Log Page)
ANA信息通过**ANA Log Page(Log Identifier 0x0C)**向主机报告。主机通过Get Log Page命令读取每个Namespace的ANA状态:
// ANA Log Page 头部结构(简化)
struct nvme_ana_log {
__le64 num_ctrl; // 控制器数量
__le64 num_ns; // 命名空间数量
struct nvme_ana_entry entries[]; // ANA条目数组
};
struct nvme_ana_entry {
__le32 nsid; // Namespace ID
__u8 anagrpid; // ANA组ID
__u8 rsvd[3];
__le64 nuse; // 已使用容量
__le64 nsze; // 总容量
};
每个ANA Group(ANAGRP)对应一组具有相同ANA行为的Namespace。控制器通过ANA Group ID将Namespace分组,同一组内的Namespace在同一路径上的ANA状态始终一致。
4.3 ANA状态转换机制
当路径状态发生变化时(例如控制器故障恢复、负载均衡触发状态切换),SSD通过**AER(Asynchronous Event Request)**通知主机ANA状态发生了变化:
ANA状态变化通知流程
SSD控制器 主机驱动
│ │
│ ANA状态变化(如故障恢复) │
│──────────────────────────▶│ AER通知:ANA Change
│ │
│ │ 主机发起Get Log Page(0x0C)
│◀──────────────────────────│
│ │
│ 返回最新ANA状态表 │
│──────────────────────────▶│
│ │ 更新路径优先级
│ │ 调整I/O调度策略
4.4 ANA Group ID与路径关联
ANA通过Controller ID + ANA Group ID的组合来描述"哪个控制器上的哪组Namespace处于什么状态":
典型双控存储的ANA拓扑
┌──────────────────┐ ┌──────────────────┐
│ 控制器A (Ctrl 1) │ │ 控制器B (Ctrl 2) │
│ Port A │ │ Port B │
└────────┬─────────┘ └────────┬─────────┘
│ │
└───────────┬─────────────┘
▼
┌─────────────────┐
│ Namespace 1 │─── ANA Group 1
│ Namespace 2 │─── ANA Group 1
│ Namespace 3 │─── ANA Group 2
└─────────────────┘
访问路径矩阵(示例):
Ctrl 1 (Port A) Ctrl 2 (Port B)
ANA Group 1 Optimized Non-Optimized
ANA Group 2 Non-Optimized Optimized
这种设计的优势在于:
- 可以将Namespace分配给不同控制器作为"属主",实现负载分担
- 每个Namespace都有一条优化路径和一条非优化路径
- 故障时非优化路径自动提升为优化路径(或继续以非优化模式提供服务)
4.5 NVMe 2.0 ANA增强特性
NVMe 2.0规范对ANA进行了多项增强:
五、SAS双端口与ALUA协议原理
5.1 SAS双端口的物理层原理
SAS(Serial Attached SCSI)协议从设计之初就天然支持双端口。SAS标准定义了两种双端口模式:
宽端口(Wide Port)模式:
- 多个物理链路(PHY)聚合为一个逻辑端口
- 链路聚合提供更高带宽(4x 12G SAS = 48Gbps)
- 单控制器访问,不是真正的双路径冗余
双端口(Dual Port)模式:
- 两个独立的SAS端口,各自连接到不同的SAS域
- 连接到不同的SAS控制器/Expander
- 提供真正的路径冗余
5.2 ALUA协议模型
ALUA(Asymmetric Logical Unit Access)是SCSI SAM-5规范中定义的多路径访问标准,SAS和FC存储广泛使用:
SCSI ALUA 目标端口组模型
┌─────────────────────────────────────────────┐
│ SCSI Target │
│ │
│ ┌──────────┐ ┌──────────┐ │
│ │ Target │ │ Target │ │
│ │ Port │ │ Port │ │
│ │ Group A │ │ Group B │ │
│ │ (TPG_A) │ │ (TPG_B) │ │
│ └────┬─────┘ └────┬─────┘ │
│ │ │ │
│ └─────────┬─────────┘ │
│ ▼ │
│ ┌──────────────┐ │
│ │ LUN 0 │ │
│ │ LUN 1 │ │
│ └──────────────┘ │
└─────────────────────────────────────────────┘
每个Target Port Group(TPG)包含一个或多个物理端口,同一TPG内的端口访问LUN的性能特征一致。
5.3 ALUA四种端口访问状态
SCSI ALUA定义了四种标准的访问状态,与NVMe ANA的对应关系如下:
| Active/Optimized | 活跃/优化 | ANA Optimized |
| Active/Non-Optimized | 活跃/非优化 | ANA Non-Optimized |
| Standby | 待命 | ANA Inaccessible(不可访问) |
| Unavailable | 不可用 | ANA Persistent Loss |
| Transitioning | 转换中 | ANA Change |
主机通过REPORT TARGET PORT GROUPS命令查询ALUA状态,通过SET TARGET PORT GROUPS命令请求状态切换(例如故障恢复后的回切)。
5.4 ALUA隐式切换 vs 显式切换
ALUA支持两种切换模式:
- 隐式ALUA(Implicit ALUA):状态切换由存储阵列端自动完成,主机只能查询不能控制。适用于简单场景。
- 显式ALUA(Explicit ALUA):主机可以主动发起状态切换请求。适用于需要精细控制路径的场景。
显式ALUA切换流程
主机 initiator 存储 target
│ │
│ SET TARGET PORT GROUPS │
│ (请求切换TPG_A为Optimized) │
│───────────────────────────▶│
│ │ 执行切换
│ │ (缓存刷新 + 路径切换)
│ GOOD / CHECK CONDITION │
│◀───────────────────────────│
│ │
│ REPORT TPGS (确认状态) │
│───────────────────────────▶│
│◀───────────────────────────│
六、Linux内核多路径子系统架构:DM-Multipath / nvme-multipath
6.1 Linux多路径技术的两条路线
Linux系统中有两种主要的多路径实现方案,分别针对不同的存储协议:
Linux多路径技术栈
┌─────────────────────────────────────────────────┐
│ 应用程序 / 文件系统 │
└─────────────────────┬───────────────────────────┘
│
┌─────────────┴─────────────┐
▼ ▼
┌───────────────┐ ┌───────────────────┐
│ DM-Multipath │ │ nvme-multipath │
│ (device-mapper) │ │ (native NVMe) │
└───────┬───────┘ └─────────┬─────────┘
│ │
▼ ▼
┌───────────────┐ ┌───────────────────┐
│ SCSI / SAS / │ │ NVMe 子系统 │
│ FC 中层 │ │ (ana/iopath) │
└───────┬───────┘ └─────────┬─────────┘
│ │
▼ ▼
多路径SAS SSD 双端口NVMe SSD
/ FC SAN存储 / NVMe-oF远程存储
6.2 DM-Multipath 架构详解
DM-Multipath是基于Device Mapper框架的通用多路径解决方案,支持SCSI/SAS/FC/iSCSI等多种协议。
核心组件:
DM-Multipath 组件架构
┌─────────────────────────────────────────────────────┐
│ multipathd (用户空间守护进程) │
│ – 监控路径健康状态 │
│ – 执行路径切换(failover / failback) │
│ – 基于multipath.conf配置策略 │
└────────────┬────────────────────────────────────────┘
│ sysfs / uevents
▼
┌─────────────────────────────────────────────────────┐
│ device-mapper 内核子系统 │
│ ┌──────────────┐ ┌──────────────┐ │
│ │ dm核心层 │ │ multipath目标│ │
│ │ (映射管理) │──▶│ (I/O调度) │ │
│ └──────────────┘ └──────┬───────┘ │
│ │ │
│ ┌─────────────┼─────────────┐ │
│ ▼ ▼ ▼ │
│ 路径1 路径2 路径N │
│ (sd[a]) (sd[b]) … │
└─────────────────────────────────────────────────────┘
6.3 DM-Multipath的I/O调度策略
DM-Multipath支持多种I/O路径调度策略(path_selector):
| service-time | 基于服务时间的动态负载均衡 | 默认,性能最优 |
| round-robin 0 | 轮询调度 | 对称路径,简单负载均衡 |
| queue-length | 基于队列长度的负载均衡 | 非对称路径,按负载分配 |
| failover | 主备模式,仅使用一条路径 | 非对称存储,节省非优化路径资源 |
6.4 NVMe Native Multipath 架构
NVMe原生多路径是Linux内核4.15+引入的特性,直接集成在NVMe子系统中,无需经过Device Mapper层:
// 内核源码:drivers/nvme/host/multipath.c
// 核心数据结构:
struct nvme_ns_head {
struct list_head list;
struct nvme_subsystem *subsys;
struct gendisk *disk; // 对上层呈现的通用磁盘
struct list_head list; // 所有路径(ns)链表
struct srcu_struct srcu; // 安全引用计数
int nr_live_paths; // 活跃路径数
u32 nsid; // Namespace ID
bool is_ana; // 是否支持ANA
// …
};
struct nvme_ns {
struct list_head siblings; // 挂入ns_head的list
struct nvme_ctrl *ctrl; // 所属控制器(路径)
struct nvme_ns_head *head; // 指向ns_head
int ana_state; // 当前路径的ANA状态
// …
};
核心设计思想:每个Namespace通过nvme_ns_head统一呈现给块层,每个路径对应一个nvme_ns结构体。I/O提交时,内核根据ANA状态和路径健康度选择最优路径。
6.5 DM-Multipath vs NVMe Native Multipath 对比
| 支持协议 | SCSI/SAS/FC/iSCSI/NVMe | 仅NVMe(含NVMe-oF) |
| 内核层级 | Device Mapper层 | NVMe子系统原生 |
| 开销 | 较高(多一层DM映射) | 较低(路径选择在NVMe层完成) |
| 配置复杂度 | 高(需配置multipath.conf) | 低(自动发现) |
| 策略灵活性 | 高(丰富的调度策略) | 中(基于ANA的round-robin) |
| 适用场景 | 传统SAN存储、混合协议 | 全NVMe环境、云原生 |
七、NVMe Multipath 内核实现与I/O路径调度算法
7.1 I/O提交路径选择逻辑
NVMe多路径的核心函数是nvme_find_path(),负责在I/O提交时选择合适的路径:
// 内核源码:drivers/nvme/host/multipath.c (简化逻辑)
static struct nvme_ns *nvme_find_path(struct nvme_ns_head *head)
{
struct nvme_ns *ns, *fallback = NULL;
list_for_each_entry_rcu(ns, &head->list, siblings) {
// 跳过未就绪或离线的路径
if (!nvme_path_is_active(ns))
continue;
// 优先选择ANA Optimized状态的路径
if (ns->ana_state == NVME_ANA_OPTIMIZED)
return ns;
// 次优:ANA Non-Optimized路径(可用但性能较低)
if (ns->ana_state == NVME_ANA_NONOPTIMIZED) {
if (!fallback)
fallback = ns;
}
}
// 如果有Non-Optimized路径,返回之
if (fallback)
return fallback;
// 没有可用路径
return NULL;
}
路径选择优先级:
7.2 多路径I/O错误重试机制
当某条路径上的I/O失败时,NVMe多路径会尝试在其他路径上重试:
多路径I/O失败重试流程
应用层
│
▼ 提交I/O
块层 (bio)
│
▼
nvme_ns_head → nvme_find_path() → 选择路径A
│
▼
路径A提交I/O ──→ I/O失败(路径断开/超时)
│
▼
nvme_mpath_end_request() → 检查是否可重试
│
├─ 是 → bio重新排队,重新调用nvme_find_path()
│ 选择路径B(Optimized/Non-Optimized)
│ 路径B提交I/O → 成功 / 失败
│
└─ 否(所有路径均失败)→ 向上返回错误
关键重试决策点在nvme_failover_req()函数中:
// 内核源码:drivers/nvme/host/multipath.c
static blk_status_t nvme_failover_req(struct request *req)
{
struct nvme_ns *ns = req->q->queuedata;
// 检查是否为可重试的路径错误
if (!nvme_should_retry_other_path(req))
return BLK_STS_IOERR;
// 标记当前路径为失败状态
nvme_path_mark_failed(ns);
// 将请求重新入队,等待重新路径选择
blk_steal_bios(ns->head->requeue_list, req);
blk_mq_run_hw_queues(ns->head->disk->queue, true);
return BLK_STS_OK; // 已处理,不向上层报错
}
7.3 ANA状态变更处理
当收到AER通知的ANA状态变化时,内核通过以下流程更新路径状态:
// 简化流程
nvme_ana_work() {
1. 发送Get Log Page命令获取ANA Log
2. 解析每个ANAGRP的状态
3. 遍历每个Namespace,更新其ana_state
4. 触发块层队列刷新(blk_mq_update_nr_hw_queues)
5. 唤醒等待中的I/O
}
八、故障切换机制与路径检测算法
8.1 故障检测的三种方式
多路径系统检测路径故障主要有三种方式:
| I/O被动检测 | I/O提交失败后发现路径故障 | 等于I/O超时时间(30s默认) | 低 |
| 主动健康检查 | 周期性发送探测命令(Test Unit Ready / Keep Alive) | 探测周期(5s~30s) | 中 |
| 异步事件通知 | 设备主动发送AER/事件通知 | ~ms级(设备主动上报) | 极低 |
8.2 NVMe Keep Alive 机制
NVMe 1.3+规范引入了Keep Alive机制,用于检测控制器是否仍然存活:
NVMe Keep Alive 时序
Host Controller
│ │
│ Keep Alive Command │
│ ─────────────────────────────▶│
│ │ 正常响应
│ Completion (SUCCESS) │
│ ◀─────────────────────────────│
│ │
│ … 下一个周期 … │
│ │
│ Keep Alive Command │
│ ─────────────────────────────▶│ (控制器已故障)
│ │ 无响应
│ 超时 (KATO * 2) │
│ ──路径失效检测── │
│ 触发故障切换 │
**KATO(Keep Alive Timeout)**由主机通过Set Features命令配置,企业级场景通常设为2~5秒,以实现快速故障检测。
8.3 路径恢复与回切策略
路径故障恢复后,是否将I/O切回原路径(failback)是一个重要策略决策:
| Immediate(立即回切) | 路径恢复后立即切回优化路径 | 对性能敏感,切换成本低 |
| Manual(手动回切) | 需要管理员手动触发回切 | 对稳定性要求极高,避免切换抖动 |
| Followover(跟踪主用) | 始终跟随当前最优路径,不主动回切 | Active-Passive模式,避免乒乓效应 |
| Delayed(延迟回切) | 路径恢复后等待一段时间再回切 | 路径不稳定,防止频繁切换 |
乒乓效应(Ping-Pong Effect):当路径间歇性故障时,如果立即回切,I/O会在两条路径之间反复切换,导致性能剧烈波动。延迟回切策略是解决乒乓效应的常用手段。
8.4 路径故障切换时间构成
完整的故障切换时间由以下几个部分组成:
故障切换总时间 = 故障检测时间 + 缓存刷新时间 + 路径激活时间 + I/O恢复时间
典型企业级场景下的各阶段耗时(实测数据):
┌─────────────────────┬────────────┐
│ 阶段 │ 耗时 │
├─────────────────────┼────────────┤
│ 故障检测(KATO) │ 2~5s │
│ 缓存刷新(脏数据) │ 10~100ms │
│ 路径激活/ANA切换 │ 1~10ms │
│ I/O恢复(队列恢复) │ < 1ms │
├─────────────────────┼────────────┤
│ 总切换时间 │ 2~5s │
└─────────────────────┴────────────┘
优化关键:故障检测时间通常占据总切换时间的90%以上。通过缩短KATO、启用AER通知、或结合应用层心跳,可以将故障检测时间缩短到秒级甚至亚秒级。
九、双端口SSD在HA双活存储阵列中的应用
9.1 双控存储阵列的典型架构
企业级双活存储阵列(Active-Active Dual Controller)是双端口SSD最典型的应用场景:
双控全闪阵列架构
┌─────────────────────────────────────────┐
│ 存储控制器A (Active) │
│ ┌──────┐ ┌──────┐ ┌──────┐ │
│ │ 前端 │ │ FTL/ │ │ 后端 │ │
│ │ 端口 │ │ Cache│ │ SAS/NVMe│ │
│ └───┬───┘ └──┬───┘ └───┬───┘ │
└──────┼─────────┼──────────┼──────────────┘
│ │ │
┌───────────┘ │ └───────────┐
│ 主机侧链路 │ PCIe/PCIe │ 后端SAS/NVMe
▼ ▼ 互联 ▼
┌──────────┐ ┌──────────┐ ┌───────────────────┐
│ FC/iSCSI │ │ HA 镜像 │ │ 双端口SSD盘柜 │
│ / NVMe-oF│ │ (缓存同步)│ │ ┌───┐ ┌───┐ ┌───┐│
│ 前端网络 │ └──────────┘ │ │SSD│ │SSD│ │…││
└──────────┘ │ └───┘ └───┘ └───┘│
▲ │ 双端口连接到双控 │
│ 主机侧链路 └───────────────────┘
┌──────┼─────────┼──────────┼──────────────┐
│ │ │ │ │
└──────┼─────────┼──────────┼──────────────┘
│ ┌───┴───┐ ┌──┴────┐ ┌──┴────┐ │
│ │ 前端 │ │ FTL/ │ │ 后端 │ │
│ │ 端口 │ │ Cache │ │ SAS/NVMe│ │
│ └───────┘ └───────┘ └───────┘ │
│ 存储控制器B (Active) │
└─────────────────────────────────────────┘
9.2 双控阵列中的LUN归属与ALUA
在双控阵列中,每个LUN/Namespace都有一个"属主控制器"(Owner Controller):
- 通过属主控制器访问 → Optimized路径(直接从缓存+介质读取)
- 通过非属主控制器访问 → Non-Optimized路径(需通过控制器间互联转发I/O)
LUN归属与路径性能
Controller A Controller B
(属主) (非属主)
LUN 1 读请求 ──▶ 直接读缓存/介质 ◀──转发─── 接收主机I/O
直接响应主机 │
▼
控制器间互联链路
(PCIe/InfiniBand/RoCE)
非优化路径的性能损耗:
- 延迟增加:通常增加 50% ~ 200%(需跨控制器转发)
- 带宽下降:受限于控制器间互联带宽
- CPU开销:两个控制器都需要处理I/O
9.3 双活(Active-Active)与双控(Dual Controller)的区别
注意区分两个容易混淆的概念:
| 双控制器 | 硬件上有两个控制器 | 硬件级冗余 |
| 双活(Active-Active) | 两个控制器同时承载I/O | 工作模式 |
| Active-Passive双控 | 只有一个控制器承载I/O | 工作模式 |
| ALUA双控 | 两个控制器都能访问I/O,但性能不对称 | 工作模式 |
真正的Active-Active双活存储需要满足:
- 两个控制器同时处理主机I/O
- 任何一个控制器故障,另一个接管全部负载
- LUN可以在控制器间动态迁移(负载均衡)
- 缓存镜像(Cache Mirroring)保证数据一致性
9.4 缓存镜像与数据一致性
双控阵列的一个核心技术挑战是缓存一致性。当控制器A的缓存中有脏数据时,如果控制器A突然故障,这些脏数据必须不能丢失。
缓存镜像(Cache Mirroring)机制:
写入流程(控制器A收到写请求)
1. 控制器A接收主机写I/O
│
▼
2. 数据写入控制器A的写缓存
│
▼
3. 同时将数据通过PCIe/IB互联镜像到控制器B的缓存
│
▼
4. 收到控制器B的镜像确认后,向主机返回写完成
│
▼
5. (后台)控制器A将数据刷入SSD介质
│
▼
6. 刷盘完成后,两个控制器的缓存副本均可释放
镜像策略对比:
- 写穿透镜像(Write-Through Mirror):写必须同时落到两个控制器缓存才返回,数据安全但延迟较高
- 写回镜像(Write-Back Mirror):写入本地缓存即返回,后台异步镜像,性能高但有秒级数据丢失风险
- 同步镜像:主流方案,镜像完成才返回写确认,平衡性能与安全
十、性能基准测试:单路径 vs 双路径 vs 多路径聚合
10.1 测试环境与方法
测试平台配置:
- 服务器:双路Intel Xeon Gold 6330(2.0GHz, 28C/56T)
- SSD:三星PM9A3 3.84TB U.2双端口版(PCIe 4.0 x4双端口)
- 主板:双PCIe 4.0 x16 CPU直连通道
- 操作系统:Ubuntu 22.04 LTS,内核5.15.0-92-generic
- 测试工具:fio 3.30 + nvme-cli 2.1.2
测试配置:
- 块大小:4KB(随机)/ 128KB(顺序)
- 队列深度:QD=1, 8, 32, 128, 512
- 工作负载:randread / randwrite / read / write
- 测试时长:每配置300秒
- 双路径模式:NVMe Native Multipath + Round-Robin
10.2 随机读性能对比(4KB随机读)
| QD=1 | 15,230 | 14,980 | -1.6% | 78μs | 85μs |
| QD=8 | 92,450 | 168,320 | +82.1% | 112μs | 128μs |
| QD=32 | 185,640 | 342,150 | +84.3% | 215μs | 245μs |
| QD=128 | 245,830 | 458,720 | +86.6% | 620μs | 680μs |
| QD=512 | 268,120 | 502,480 | +87.4% | 2,350μs | 2,520μs |
随机读IOPS对比 (4KB, IOPS →)
QD=1 |■■■■■■■■■■■ 单路径 15K
|■■■■■■■■■■■ 双路径 14.9K ← 低QD下无优势
QD=8 |■■■■■■■■■■■■■■■■ 单路径 92K
|■■■■■■■■■■■■■■■■■■■■■■■■■■■ 双路径 168K ← 接近翻倍
QD=128 |■■■■■■■■■■■■■■■■■■■■■ 单路径 245K
|■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ 双路径 458K ← +86.6%
结论:低队列深度(QD=1)下双路径没有性能优势,反而因为路径选择逻辑略有延迟增加。但在高并发场景下(QD≥8),双端口可提供接近翻倍的IOPS,提升幅度在80%~90%之间(受限于内部共享资源如DRAM带宽、FTL处理能力)。
10.3 顺序读带宽对比(128KB顺序读)
| QD=1 | 3,420 | 3,380 | -1.2% |
| QD=8 | 6,850 | 7,200 | +5.1% |
| QD=32 | 7,020 | 7,350 | +4.7% |
| QD=128 | 7,080 | 7,420 | +4.8% |
分析:顺序读带宽提升有限(仅5%左右),因为顺序读的瓶颈已经不在PCIe链路,而在NAND闪存的读带宽。双端口提供的额外PCIe带宽无法被充分利用。随机读的提升来源于两个端口可以并行访问不同的NAND Die/Plane。
10.4 故障切换实测数据
测试方法:在fio持续打满I/O的过程中,通过nvme disconnect命令模拟路径故障,测量I/O中断时间。
| 单路径断开 | 2.1秒 | I/O短暂冻结后恢复到另一路径 |
| 写密集负载 | 3.4秒 | 需等待缓存刷新和元数据同步 |
| 读密集负载 | 0.8秒 | 读I/O更快切换到备用路径 |
| KATO=2s配置 | 2.3秒 | 检测+切换总时间 |
| KATO=500ms配置 | 0.7秒 | 快速检测配置下 |
# 查看NVMe多路径拓扑
nvme list-subsys
# 输出示例:
nvme-subsys0 – NQN=nqn.2023-01.com.example:pm9a3-01
\\
+- nvme0 pcie 0000:81:00.0 live optimized
+- nvme1 pcie 0000:41:00.0 live optimized
重要发现:实际切换时间远远短于理论超时时间(默认30秒),因为NVMe驱动会在检测到PCIe链路层错误时立即触发故障切换,而不是等待完整的I/O超时。
10.5 CPU开销对比
| 单路径NVMe | 32% | 原生NVMe驱动 |
| 双路径NVMe (native) | 38% | +19%(路径选择+管理开销) |
| 双路径DM-Multipath | 56% | +75%(DM层额外开销) |
十一、双端口SSD的一致性与数据保护挑战
11.1 双端口同时写入的一致性问题
双端口SSD面临的核心一致性挑战是:两个端口同时写入同一个LBA时,数据会是什么?
一致性要求的三个层级:
| 单元一致性 | 单个LBA的读写原子性(512B/4KB) | ✅ 是(由主控内部仲裁保证) |
| 顺序一致性 | 两端口的写操作按全局顺序可见 | ⚠️ 部分保证 |
| 因果一致性 | 一个端口写完后另一端口能立即读到最新值 | ✅ 是(共享缓存+屏障机制) |
11.2 主控内部的仲裁机制
双端口SSD的主控芯片内置了互斥仲裁引擎,确保对同一NAND块的操作不会冲突:
双端口I/O仲裁机制
Port A 写入 LBA 0x1000 ──▶ ┌─────────────┐
│ 仲裁引擎 │
Port B 写入 LBA 0x1000 ──▶ │ (Mutex) │
└──────┬──────┘
│
▼
FTL执行单元
(串行处理冲突I/O)
│
▼
先完成的I/O返回成功
后完成的I/O覆盖/合并
仲裁策略:
- 基于LBA的细粒度锁:按LBA范围加锁,不冲突的I/O并行执行
- 写操作串行化:同一LBA的写操作严格串行,后写覆盖先写
- 读操作并行:读操作之间无需互斥,可并行执行
- 读写互斥:写操作期间对同一LBA的读操作需等待
11.3 NVMe Reservation机制
对于多主机共享的双端口SSD,NVMe规范通过**Reservation(预留)**机制提供更高级别的访问控制(详见Day 49):
Reservation类型与用途:
– Write Exclusive:只允许预留持有者写入
– Exclusive Access:只允许预留持有者读写
– Write Exclusive – Registrants Only:仅注册者可写
– Exclusive Access – Registrants Only:仅注册者可读写
– Write Exclusive – All Registrants:所有注册者均可写(但有协调)
– Exclusive Access – All Registrants:所有注册者均可读写
在双活环境中,通常使用Exclusive Access – All Registrants类型,配合ANA实现双活访问。
11.4 数据完整性挑战与应对
双端口SSD在以下场景面临额外的数据完整性挑战:
挑战1:两端口同时掉电
- 风险:两个端口同时失去电源,PLP电容能否支撑完整的缓存刷写?
- 应对:双端口SSD的PLP设计需要考虑双端口同时掉电场景,电容容量按最大缓存数据量设计
挑战2:单端口固件崩溃
- 风险:一个端口的固件逻辑异常,可能写入脏数据到共享介质
- 应对:单芯片方案的两端口共享同一固件核心,崩溃同时影响两端口;双芯片方案有更好的隔离
挑战3:缓存一致性
- 风险:两端口各自缓存LBA映射表,可能出现不一致
- 应对:企业级双端口SSD使用单一共享的FTL缓存,通过内部互联保证一致性
十二、当日知识点小结
| 双端口SSD的价值 | 消除路径和控制器层面的单点故障,提升可用性 | 99.999%可用性目标;年停机<5.26分钟 |
| 三种访问模型 | Active-Active(对称双活)性能最优;ALUA/ANA最常用;AP最简单 | AA模式接近200%性能利用率 |
| NVMe ANA | NVMe 1.4+标准化的非对称访问机制,4种状态 | Optimized/Non-Optimized/Inaccessible/Change |
| SAS ALUA | SCSI标准的多路径访问模型,5种状态 | Active-Optimized/Active-NonOptimized/Standby/Unavailable/Transitioning |
| Linux多路径 | NVMe原生多路径(内核级)vs DM-Multipath(通用方案) | Native模式CPU开销比DM低约32% |
| 故障切换时间 | 主要由故障检测时间决定,秒级切换 | KATO=2s时总切换时间约2~5秒 |
| 性能提升 | 高并发随机读场景下IOPS提升80%90%;顺序带宽提升有限(5%) | QD=128时单路径245K → 双路径458K IOPS |
| 一致性挑战 | 单LBA原子性有保证;多LBA/多端口并发需依赖仲裁和Reservation | 主控内置细粒度LBA锁机制 |
十三、思考题
问题1:为什么在低队列深度(QD=1)下,双端口SSD的性能反而比单端口略差?从硬件架构和软件路径两个角度分析原因。
问题2:假设有一个双控Active-Active全闪阵列,每个控制器提供500K IOPS的处理能力。如果采用ALUA模式(每个LUN有一个优化路径),相比真正的对称Active-Active模式,在以下两种工作负载下的最大IOPS分别是多少?请给出推理过程:(a) 所有I/O访问同一个LUN;(b) I/O均匀分布在100个LUN上。
问题3:在NVMe-oF场景下,主机通过两条网络路径(如两路RoCE v2)连接到同一台NVMe SSD,这属于"多路径"吗?它与直连双端口SSD的多路径在故障检测、切换延迟、一致性方面有什么异同?
参考资料
-
NVMe Base Specification 2.0c – NVM Express官方规范,第8章Asymmetric Namespace Access
-
NVMe PCIe Transport Specification Revision 1.0 – NVMe PCIe传输层规范,双端口定义
-
JEDEC JESD231D:U.2 (SFF-8639) SSD Electrical Specification – U.2接口电气规范与双端口引脚定义
-
SNIA Tutorial:NVMe Multipath and High Availability – SNIA数据中心大会NVMe多路径教程
-
Linux kernel documentation:NVMe Multipath – Linux内核NVMe多路径官方文档
-
Linux kernel source:drivers/nvme/host/multipath.c – Linux内核NVMe多路径源码
-
Linux DM-Multipath Documentation – RedHat Enterprise Linux DM-Multipath官方文档
-
SAM-5 (SCSI Architecture Model – 5):ALUA定义 – T10 SCSI架构模型第5版,第5章ALUA
-
[Samsung PM9A3 Product Specification – 三星PM9A3企业级NVMe SSD产品规格书(双端口U.2版本)](https://s3.ap-northeast-2.amazonaws.com/global.semi.static/PM9A3/Product Brief/Samsung_SSD_PM9A3_Product_Brief.pdf)
-
KIOXIA CD8 Series Data Sheet – 铠侠CD8系列企业级SSD数据手册
作者简介:资深RDMA智能网卡、存储技术专家,拥有十余年DPU/RDMA/NVMe SSD芯片测试与工程经验,致力于推动高性能网络技术的开源与普及。
网硕互联帮助中心






评论前必须登录!
注册