NVMe概述

摘要:
在NVMe出现之前,大多数SSD都遵循AHCI和SATA协议,而这些协议实际上为传统HDD提供服务。NVMeCommand NVMeHost和NVMeController通过NVMeCommand交换信息。NVMeCommand的格式在NVMeSpec中定义。可以看出,NVMeCommand占用64个字节。NVMeQueueNVMe有两个队列和一个寄存器:① 提交队列② 完成队列③ DoorbellRegisterSQ和CQ位于主机的内存中,DB位于SSD的控制器中。AHCI只有一个命令队列,队列深度是固定的。32Linux的NVMe驱动程序使用一个内核独占一个队列。队列用于存储NVMeCommand,NVMeCommand是主机与SSDController通信的基本单元。应用程序的I/O请求也应转换为NVMeCommand。

目前企业SSD市场按照接口协议主要分为SATA SSD,PCIe SSD和NVMe SSD,其中SATA SSD沿用了传统的HDD使用的SATA协议,在企业应用和服务器兼容性上具有优势;而PCIe SSD则一般使用私有协议,目前已经处于比较小众的产品;NVMe SSD则在PCIe接口上使用新的标准协议NVMe,由于NVMe由大厂Intel推出并交由nvmexpress组织推广,现在被全球大部分存储企业采纳,如memblaze,huawei,samsung都推出了相关的产品

NVMe 是什么?
NVM Express(NVMe),或称非易失性内存主机控制器接口规范(Non-Volatile Memory express),,是一个逻辑设备接口规范。他是与AHCI类似的、基于设备逻辑接口的总线传输协议规范(相当于通讯协议中的应用层),用于访问通过PCI-Express(PCIe)总线附加的非易失性内存介质,虽然理论上不一定要求 PCIe 总线协议。此规范目的在于充分利用PCI-E通道的低延时以及并行性,还有当代处理器、平台与应用的并行性,在可控制的存储成本下,极大的提升固态硬盘的读写性能,降低由于AHCI接口带来的高延时,彻底解放SATA时代固态硬盘的极致性能

NVMe具体优势包括:

①NVMe是为SSD所生的。NVMe出现之前,SSD绝大多数走的是AHCI和SATA的协议,后者其实是为传统HDD服务的。与HDD相比,SSD具有更低的延时和更高的性能,AHCI已经不能跟上SSD性能发展的步伐了,已经成为制约SSD性能的瓶颈. SATA现在最高带宽就是600MB/s,nvme使得性能有数倍的提升;

②可降低延迟超过50%;

③NVMe可以把最大队列深度从32提升到64000,SSD的IOPS能力也会得到大幅提升;

④自动功耗状态切换和动态能耗管理功能大大降低功耗;

⑤NVMe标准的出现解决了不同PCIe SSD之间的驱动适用性问题。

NVMe Command

NVMe Host(Server)和NVMe Controller(SSD)都是通过NVMe Command进行信息交互。NVMe Spec中定义了NVMe Command的格式,可以看到,NVMe Command占用64字节。其中Command的前4个字节规定如下。Command Identifier作为识别这个Command的标志,Opcode通常包含Command类型(如读写,identify等)

NVMe概述第1张

 

NVMe有两种命令,一种叫Admin Command,用以Host管理和控制SSD;另外一种就是I/O Command,用以Host和SSD之间数据的传输

Opcode在这两类的基础上进行划分。下图是部分管理Command的Opcode定义:

NVMe概述第2张

 

下图是 IO command的Opcode定义:

NVMe概述第3张

 剩余的60个字节则根据Command类型定义。

NVMe Queue

NVMe中有两个队列和一个寄存器:

①Submission Queue (SQ)

②Completion Queue(CQ)

③Doorbell Register (DB)

SQ和CQ位于Host的内存中,DB则位于SSD的控制器内部。

  • 有两种SQ和CQ,一种是Admin,另外一种是I/O,前者放Admin命令,用以Host管理控制SSD,后者放置I/O命令,用以Host与SSD之间传输数据。
  • 系统中只有一对Admin SQ/CQ,它们是一一对应的关系;I/O SQ/CQ却可以很多,多达65535(64K减去一个SQ/CQ)
  • Host端每个Core可以有一个或者多个SQ,但只有一个CQ。给每个Core分配一对SQ/CQ好理解,为什么一个Core中还要多个SQ呢?一是性能需求,一个Core中有多线程,可以做到一个线程独享一个SQ;二是QoS需求,什么是QoS?Quality of Service,服务质量。实际系统中用多少个SQ,取决于系统配置和性能需求,可灵活设置I/O SQ个数
  • NVMe概述第4张
  • 作为队列,每个SQ和CQ都有一定的深度:对Admin SQ/CQ来说,其深度可以是2-4096(4K);对I/O SQ/CQ,深度可以是2-65536(64K)。队列深度也是可以配置的。AHCI只有一个命令队列,且队列深度是固定的32
  • Linux的NVMe驱动采用一个Core独占一个Queue(由Completion Queue和Submission Queue组成)的方式。这种设计避免了一个队列被多个Core竞争访问,大家都各自使用自己的Queue,互不干扰。
  • 队列用来存放NVMe Command,NVMe Command是Host与SSD Controller交流的基本单元,应用的I/O请求也要转化成NVMe Command。
  • 每条命令大小是64字节,每条命令完成状态是16字节
  • 每个SQ或者CQ有两个DB: Head DB 和Tail DB

NVMe概述第5张

SSD作为一个PCIe Endpoint通过PCIe连着Root Complex (RC), 然后RC连接着CPU和内存。 RC就是CPU的代言人 SQ位于Host内存中,Host要发送命令时,先把准备好的命令放在SQ中,然后通知SSD来取;CQ也是位于Host内存中,一个命令执行完成,成功或失败,SSD总会往CQ中写入命令完成状态。 Host发送命令时,不是直接往SSD中发送命令的,而是把命令准备好放在自己的内存中,那怎么通知SSD来获取命令执行呢?Host就是通过写SSD端的DB寄存器来告知SSD的:

NVMe概述第6张

 流程:

1.BIO封装成的Command会顺序存入Submission Queue中

2.对于Submission Queue来说,使用Tail表示最后操作的Command Index。每存入一个Command,Host就会更新Queue对应的Doorbell寄存器中的Tail值

3.NVMe没有规定Command存入队列的执行顺序,Controller可以一次取出多个Command进行批量处理,所以一个队列中的Command执行顺序是不固定的(可能导致先提交的请求后处理)

4.SSD执行命令

5.SSD Controller根据Doorbell的值,获取NVMe Command和对应数据(步骤3),待处理完成后(步骤4)将结果存入Completion Queue中

6.Controller通过中断的方式通知Host

7.将Completion Command从Completion Queue中取出,然后把队列的head值加1,并调用上层的Callback函数(完成BIO处理)

8.处理完Command后,往Completion Queue的Doorbell写入Head值,通知NVMe Controller操作完成。中断处理结束

 

 

DB的另外一个作用,就是通知作用:Host更新SQ Tail DB的同时,也是在告知SSD有新的命令需要处理;Host更新CQ Head DB的同时,也是在告知SSD,你返回的命令完成状态信息我已经处理,同时表示谢意。这里有一个对Host不公平的地方,Host对DB只能写,还仅限于写SQ Tail DB和CQ Head DB,不能读取DB

 

疑问:

1.SSD在取指的时候,是偷偷进行的,Host对此毫不知情。Host发了取指通知后,它并不清楚SSD什么时候去取命令,取了多少命令。怎么破?

答:

NVMe概述第7张

 

这是SSD往CQ中写入的命令完成状态信息(16字节)。是的,SSD往CQ中写入命令状态信息的同时,还把SQ Head DB的信息告知了Host!!这样,Host对SQ中Head和Tail的信息都有了,轻松玩转SQ

 

2.Controller写入Command后,只有中断触发通知Host,没有类似于Head/Tail机制告诉Host可以取哪些Completion Command?

答:一开始CQ中每条命令完成条目中的”P” bit初始化为0,SSD在往CQ中写入命令完成条目时,会把”P”写成1。记住一点,CQ是在Host端的内存中,Host可以检查CQ中的所有内容,当然包括”P”了。Host记住上次的Tail,然后往下一个一个检查”P”,就能得出新的Tail了。就是这样。

免责声明:文章转载自《NVMe概述》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇express-7 请求和响应对象(2)Java语言中:float数据类型在内存中是怎么存储的?下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

Ansible 系列之 Inventory 资源清单介绍

一、Inventory 库存清单文件 1.Inventory 作用 Ansible 可以在同一时间针对多个系统设施进行管理工作。它通过选择Ansible 资源清单文件中列出的系统,该清单文件默认是在/etc/ansible/hosts,也可以使用 -i <path> 进行路径的指定。文件内的格式INI 风格,中括号内为分组名。 除了这个文件之...

log.io日志实时显示

Node.js 安装 菜鸟教程Node.js安装 设置 npm 淘宝镜像 npm config set registry https://registry.npm.taobao.org npm config get registry log.io 简介 官网地址github地址 安装服务端 npm install -g log.io 配置服务端 找...

【mysql】批量更新数据

概述 批量更新mysql数据表数据,上网搜索基本都会说4~5方法,本人使用的更新方式为:INSERT ... ON DUPLICATE KEY UPDATE Syntax可参见官方网站:insert-on-duplicate 功能: 表示插入时,如果遇到了主键重复或唯一索引重复,则不执行插入操作,而是执行更新操作; 注意点: 这种方式的批量更新,不是sq...

Go语言开发Prometheus Exporter示例

一、Prometheus中的基本概念Prometheus将所有数据存储为时间序列,这里先来了解一下prometheus中的一些基本概念 指标名和标签每个时间序列都由指标名和一组键值对(也称为标签)唯一标识。 metric的格式如下: <metric name>{<label name>=<label value>, .....

23-存储案例:如何降低SSD峰值延迟

我们之前讲过,存储系统的性能很关键(参见第17讲)。我们这一讲就探讨存储方面的优化案例,是关于SSD性能的。 现在很多公司里面的高性能存储系统,一般都是基于SSD的,这主要归功于SSD价格在近几年的大幅度下降。但是,SSD也不是包治百病的灵丹妙药,也有自己的特殊性能问题。我们今天就重点讲述两点:SSD的损耗和IO访问延迟偶尔过大的问题。 这里的第二个问题可...

docker swarm 部署 prometheus 用于监控服务器

compose.yml version: "3" services: prometheus: image: prom/prometheus:v2.18.1 ports: - "9090:9090" volumes: - /var/prometheus/etc:/etc/prometheus...