

NVMe Underprinning
NVMe Practice
NVMe Host Software
BUFFER-IO For NVMe
DirectIO For NVMe
Passthrough For NVMe
IO-Uring For NVMe
SPDK For NVMe
NVMe Protocol Layer
NVM Subsystem
Controller
Namespace
Admin Queue 与 I/O Queue
Submission Queue(SQ) 与 Submission Queue Entry(SQE)
Completion Queue(CQ) 与 Completion Queue Entry(CQE)
Doorbell
Admin Command Set
Identify
Create I/O Completion Queue
Create I/O Submission Queue
Delete I/O Submission Queue
Delete I/O Completion Queue
Get Features
Set Features
Get Log Page
Asynchronous Event Request
I/O Command Set
Write
Read
Flush
Dataset Management(DSM)
Write Zeroes
Compare
NVMe OPS: Write
NVMe OPS: Read
Transport Specifications
NVMe over PCIe Transport
NVMe over RDMA Transport
NVMe over TCP Transport
In-Depth Research on NVMe Mechanisms
SPDK
DUAL PORT SSD
Multil PATH
PRP(Physical Region Page)
SGL(Scatter Gather List)
SPEC
- NVMe Base Specification 2.3



在 SSD 大规模普及之前,存储接口主要围绕机械硬盘(HDD)的特性来设计, 机械硬盘的瓶颈在于磁头寻道和盘片旋转,随机 I/O 延迟动辄数毫秒,顺序带宽也只有一百多 MB/s. 因此,当时的主流协议: SATA/AHCI 和 SCSI 都做了大量”迁就”机械特性的设计, 单队列或有限队列、较深的命令缓冲、中断驱动为主、协议本身相对厚重.

当 NAND 闪存 SSD 出现后,硬件特性发生了根本性质变, 访问延迟从机械硬盘的毫秒级骤降到微秒级甚至更低,内部并行度极高,依托多 Channel、多 Die、多 Plane 的架构可以同时处理海量请求,随机读写能力因此暴涨,IOPS 从过去的几万轻松跃升至几十万甚至上百万,顺序带宽也迅速突破 GB/s 级别,彻底拉开了与传统机械硬盘的性能差距. 然而原有的主机接口协议和软件栈却几乎完全没有跟上这种变化,依然沿用着为机械硬盘设计的单队列、高开销、中断驱动模式,导致硬件的强大潜力无法充分释放,最终成为整个存储路径上最严重的瓶颈. 下面用几个具体场景说明问题有多严重:
- 队列深度与并行度严重不足: AHCI 只支持一个命令队列且深度固定为 32,意味着主机一次最多只能向 SSD 下发 32 条命令,而现代企业级 NVMe SSD 内部往往拥有几十甚至上百个独立的 NAND 通道和 Die,硬件本身完全有能力同时处理数千条命令,结果就是即使 SSD 硬件再快,主机侧也只能”一勺一勺”地喂命令,大量内部并行资源被闲置,数据库随机读、虚拟机高并发 I/O 以及 AI 训练时的 checkpoint 与数据加载,都会明显感受到这种”喂不饱”的感觉.
- 协议与软件栈开销过大: 传统路径大致是应用经过 VFS、块层、SCSI 中层再到驱动最终到达硬件,每一层都伴随着各自的数据结构转换、锁竞争和中断处理,这些软件开销对于机械硬盘的毫秒级延迟而言几乎可以忽略,但对微秒级的 SSD 来说却经常占比超过 50% 甚至更高,典型表现就是高 IOPS 时 CPU 被中断处理彻底打满形成 interrupt storm、多核系统下锁竞争异常严重、延迟长尾非常明显导致 P99 和 P999 延迟远高于平均值,因此在高频交易、实时推荐以及 AI 推理的 KVCache 落盘等需要极低延迟的场景中,这种开销已经变得完全不可接受.
- 多核扩展性差: 现代服务器动辄拥有几十上百个 CPU 核心,计算能力大幅提升,但 AHCI 的单队列模型以及早期 SCSI 驱动对多队列支持的不完善,却让所有 I/O 请求最终都被迫挤在少数几个硬件队列或全局锁上,导致多核优势根本无法发挥,核心数越多,存储路径的锁竞争和调度开销反而越严重,扩展性不升反降,最终出现”加核不加性能”的尴尬局面.
- 实际业务中的痛点举例:
- 数据库场景: MySQL/PostgreSQL 在高并发 OLTP 下,随机读延迟和 IOPS 直接受限于 AHCI/SCSI 队列深度和软件开销,CPU 利用率居高不下,但存储带宽却吃不满
- 虚拟化与云: 一台物理机上跑几十上百个虚拟机,每个虚拟机都有自己的 I/O 流, 传统接口很难高效隔离和调度这些流,导致”吵闹邻居”问题严重
- 大数据与 AI 训练: 大模型训练需要频繁做 Checkpoint,或者把 KVCache 卸载到高速存储, 传统协议在顺序大块写入和随机小块混合负载下,延迟抖动大,吞吐上不去,直接影响训练效率
- 超融合与分布式存储: Ceph、MinIO、自研分布式存储在节点内部使用本地 SSD 时,如果底层还是 AHCI/SCSI,单节点性能天花板很低,被迫用更多节点堆性能,成本和管理复杂度急剧上升
- 边缘与嵌入式高带宽场景: 即使是消费级或边缘设备,PCIe 通道已经很宽,但 SATA 接口带宽成为瓶颈,无法发挥闪存潜力
总的来看,NVMe 要解决的核心矛盾在于: 闪存硬件早已具备高并行、低延迟和高带宽的能力,但主机侧的接口协议与软件栈却依然停留在机械硬盘时代的设计思路中,两者之间的鸿沟随着 SSD 性能的持续跃升而越来越大,最终使存储系统的性能瓶颈彻底从“介质本身”转移到了“接口协议与软件栈”之上.

在 NVMe 标准正式落地之前,业界为了缓解传统 AHCI/SCSI 接口的瓶颈,已经出现了几类主流的过渡方案. 最常见的做法是把 AHCI 协议直接跑在 PCIe 通道上(AHCI over PCIe),这样虽然解决了 SATA 接口的带宽天花板问题,却依然继承了 AHCI 单队列、深度仅 32 的根本缺陷,性能提升非常有限. 企业级市场则更多转向 SAS SSD,它在队列深度、双端口冗余和可靠性上明显优于 SATA,但底层仍基于厚重的 SCSI 协议,软件开销和扩展性瓶颈并没有被真正消除. 真正把性能推向新高度的,是当时以 Fusion-io、Virident 等为代表的私有 PCIe Flash 方案, 这些产品采用定制控制器和专有驱动,几乎完全绕过传统块层与标准协议,直接把闪存的高并行、低延迟潜力释放出来,在数据库、HPC 等高端场景中展现出远超 SAS/SATA 的表现. 然而,这种”性能换生态”的路线也带来了严重的副作用: 驱动碎片化、管理工具不统一、多厂商兼容性差、厂商锁定风险高. 正是这些过渡方案在实际落地中暴露出的问题, 既证明了“PCIe + 精简软件栈”能够带来巨大收益,又凸显了缺乏统一标准的痛苦, 最终推动行业在 2009 年前后正式启动 NVM Express 的标准化工作,试图用一套开放、高效、可扩展的接口,彻底取代此前所有临时性的妥协方案.

正是在这样的背景下,业界意识到单纯依靠私有方案或对旧协议修修补补已经无法从根本上解决问题,必须重新定义一套面向非易失性存储器的主机接口标准. 于是,NVM Express(简称 NVMe)应运而生. NVMe 从一开始就彻底抛弃了为机械硬盘设计的思维包袱,直接针对闪存的高并行、低延迟和高带宽特性进行设计. 它通过支持多达数万个队列、每个队列深度可达数万条命令的架构,让主机能够真正匹配现代 SSD 内部的海量并行能力. 同时大幅精简协议开销,采用内存映射的门铃机制和高效的完成路径,把软件栈的延迟降到极低水平. 更重要的是,它原生基于 PCIe,并预留了良好的扩展性,为后续的更高带宽、虚拟化、网络化存储(NVMe over Fabrics)等演进留下了充足空间.

