前提

NVME

什么是NVME?

  1. NVMe是为PCIe制定的标准接口协议。
  2. 解除了旧标准施放在SSD上的各种限制。
  3. 支持所有常见的操作系统。
  4. 良好的可拓展性。
  5. 具有低延迟,低能耗,高性能等优点。

传统的AHCI协议具有较强的兼容性,但是当与通过PCIe总线连接的SSD一起使用时,无法提供最佳的性能。而NVMe的设计充分利用了PCIe SSD的低延迟和并行性,并兼顾可CPU与平台构架,最大程度的发挥SSD的性能。

第一:NVMe是一种接口协议,不是指的接口,所谓的协议就是某种规则,比如生活中不同的公路,可以看作是不同的接口,如果一条公路按照高速公路的规则来运行,那么就算是同样的路,也会比行人、自行车、汽车都能走的普通公路速度快得多;
第二:NVMe标准是面向PCI-E固态硬盘的,怎么理解这个呢,我们知道电脑的CPU是核心计算单元,所有程序指令的计算处理都是由CPU完成,PCI-E相当于一条直接跟CPU打交道的绿色通道,所以PCI-E固态硬盘实际上就是固态硬盘可以直接跟CPU打交道,意味着速度可以更快;
第三:除了高速公路上的绿色通道特性之外,NVMe还具有超宽的车道,意思是同一时间可以跑更多的数据在上面,不光跑得快,货还拉得多;
第四:还有一个重要特性是它的功耗很低,这里功耗低并不是指的省油,而是综合管理能力带来的能耗控制,由于在上面跑起来都非常快,所以一旦没数据了,立马让工作人员进入休息状态,长时间没数据,立马放假。对于平板跟笔记本来说,可显著提高电池续航能力。

SPDK

什么是SPDK

英特尔开发了SPDK(Storage Performance Development Kit),包含一套驱动程序,以及一整套端到端的存储参考架构。
首先要明确spdk是一个框架,而不是一个分布式系统,spdk的基石是用户态(user space)、轮询(polled-mode)、异步(asynchronous)、无锁(lockless)
SPDK基于Nvme驱动提供了零拷贝、高并发直接从用户态访问ssd的特性
其最初的目的是为了优化块存储落盘。但随着spdk的持续演进,大家发现spdk可以优化存储软件栈的各个方面。很多分布式存储系统都在思考如何吸纳spdk框架,或是采用spdk代表的高性能存储技术,来优化整条IO链路

使用SPDK原因

固态硬盘SSD正在迅速扩展它在数据中心中的份额,相较于传统存储介质,相较于传统机械硬盘性能耗电等优势明显。随着更新的闪存介质投入市场(如3D NAND),这些优势还在不断扩大。

这些新的设备目前大都基于NVMe:NVMe准确的说是目前最新的存储设备通信协议。现在一块基于NVMe的SSD硬盘的性能比一个企业级磁盘阵列还要好。

用户在集成新一代的NVMe设备,会碰到很大的挑战。因为NVMe硬盘的吞吐量和时延表现太好了就IOPS而言,比传统SAS或SATA温氏磁盘快上千倍,也比之前的SATA SSD快5~10倍。一般存储软件的表现,相对于NVMe来说,在整个IO事务中消耗的时间百分比就显得太多了。

nvme(硬件)已经快到一定程度了,尤其是软件已经赶不上他了,此时软件反而成为了系统IO的瓶颈。换句话说,存储软件栈的性能和效率在整个存储系统中越来越重要。
举个例子:我们从北京乘飞机到美国加州,按照当前的飞行速度(假设为机械硬盘),在天上需要13个小时。这种情况下,你安检的时间,过海关的时间,候机的时间,加起来3个小时,相对于总共的13+3=16个小时也不算长。设想现在飞机的飞行速度(硬件速度)提高了100倍(使用了NVME设备),不到10分钟的飞行时间,就可在加州落地,这时3个小时(软件速度)的地面手续就显得太长了。这时软件拖慢了整体时间,我们就需要提高安检,候机时间等,也就是提高软件效率。

SPDK关键技术

相对于传统IO方式,SPDK运用了以下关键技术实现其高性能方案。

用户态(空间)

定义:什么是用户空间:Kernel space 是 Linux 内核的运行空间,User space 是用户程序的运行空间。为了安全系统稳定性,它们是隔离的,即使用户的程序崩溃了,内核也不受影响。
Kernel space 可以执行任意命令,调用系统的一切资源;User space 只能执行简单的运算,不能直接调用系统资源,必须通过系统接口(又称 system call),才能向内核发出指令也叫系统调用。

SPDK运行在用户态的实现

第一:驱动是一个直接连接并控制计算机硬件的软件。
第二:操作系统将根据权限级别将系统虚拟内存分为两类:用户空间和内核空间。
通常情况,驱动运行在内核空间,我们应用程序访问磁盘,读取网卡的数据,新建一个线程都需要通过系统调用接口,完成从用户态到内存态的切换
但是SPDK包含的驱动运行在用户空间,但是这些驱动仍旧直接和硬件设备相连。也就是直接绕过内核空间。
SPDK为了控制硬件设备,他先指示操作系统放弃对该硬件的控制,这样就不会走内核空间了。比如在Linux上解除NvMe设备的绑定,则对应的/dev/nvme1就会消失。然后通过驱动直接控制硬件设备这样更快。

SPDK选择用户态的好处

传统IO是在用户态和内核态频繁切换,这会造成大量开销。而我们的设备驱动代码运行在用户态意味着,在定义上驱动代码不会运行在内核中。减少系统调用,避免内核上下文切换和中断的处理开销,从而节省了大量的CPU负担。允许更多的时间被用来做实际的数据存储。

轮询模式

采用轮询模式改变了传统I/O的基本模型

传统方式IO方式

一般来说读写数据的运作方式是这样的:
OS kernel请求一组数据,硬盘回应“嗯,没问题”,但是磁盘IO较慢,所以需要一点时间来准备数据,准备好了就会告诉OS kernel准备好了。假设现在已经准备好了,就会给CPU发送一个中断信号,通知OS说我的数据准备好了,可以来取数据了。这就是中断的方式。

有IO需要处理时就请求一个中断,CPU先去处理其他事务,等收到中断后才进行资源调度来处理IO。

但是注意中断是有开销的,需要切换资源

轮询工作

当磁盘速度远慢于CPU时,CPU中断处理资源充沛,中断机制是能对这些IO任务应对自如的。

但是当硬盘设备速度很快,马上就可以把数据准备好,也就是磁盘IO几乎不需要等待了,再使用中断,本来硬盘IO数据立刻都准备好了,而CPU切换到其他地方执行去了,然后再中断回来取数据,这就会造成没必要的开销并且对性能造成影响。

在低速设备中,中断开销只占整个I/O时间的一个很小的百分比。然而,在固态设备的时代,持续引入更低延迟的持久化设备,中断开销成为了整个I/O时间中不能被忽视的部分。继续使用中断的方式会大大浪费硬盘性能。

所以解决方案:对于超高速设备(比如这里的nvme磁盘,基于RAM的缓存盘)以一种叫做“轮询”的模式运作。

所以我们采用轮询的工作方式:我们提交完io 请求之后,就一直通过轮询的方式来判断io 请求是否完成。SPDK架构中也是通过这样的方式,而不是依靠中断,在高速设备上用于取代中断的访问方式。这样会一直占用CPU,但是由于硬盘IO很快,这样带来的好处是降低总延迟和延迟抖动。通俗的来讲spdk运行时会占用满指定的CPU core,其本质就是一个大的while死循环,占满一个cpu core。去连续的跑用户指定的poller,轮询队列。

注意:是中断驱动处理还是轮询驱动处理,取决于系统硬件的搭配方式,不同的条件会匹配不同的优化策略。我们使用轮询是因为使用高速存储设备存储IO速度极快。

总结

spdk目前的的应用场景主要是针对块存储,可以说块存储的整个存储的基石,再其之上我们又构建了各种文件存储、对象存储、表格存储、数据库等等。

RDMA

DMA

DMA(直接内存访问)是一种能力,允许在计算机主板上的设备直接把数据发送到内存中去,数据搬运不需要CPU的参与。

传统内存访问需要通过CPU进行数据copy来移动数据,通过CPU将内存中的Buffer1移动到Buffer2中。DMA模式:可以同DMA Engine之间通过硬件将数据从Buffer1移动到Buffer2,而不需要操作系统CPU的参与,大大降低了CPU Copy的开销。
image.png

RDMA

RDMA是一种概念,在两个或者多个计算机进行通讯的时候使用DMA, 从一个主机的内存直接访问另一个主机的内存。
image.png
RDMA是一种host-offload, host-bypass技术,允许应用程序(包括存储)在它们的内存空间之间直接做数据传输。具有RDMA引擎的以太网卡(RNIC)–而不是host–负责管理源和目标之间的可靠连接。使用RNIC的应用程序之间使用专注的QP和CQ进行通讯:

  1. 每一个应用程序可以有很多QP和CQ
  2. 每一个QP包括一个SQ和RQ
  3. 每一个CQ可以跟多个SQ或者RQ相关联

image.png

RDMA的优势

传统的TCP/IP技术在数据包处理过程中,要经过操作系统及其他软件层,需要占用大量的服务器资源和内存总线带宽,数据在系统内存、处理器缓存和网络控制器缓存之间来回进行复制移动,给服务器的CPU和内存造成了沉重负担。尤其是网络带宽、处理器速度与内存带宽三者的严重”不匹配性”,更加剧了网络延迟效应。

RDMA是一种新的直接内存访问技术,RDMA让计算机可以直接存取其他计算机的内存,而不需要经过处理器的处理。RDMA将数据从一个系统快速移动到远程系统的内存中,而不对操作系统造成任何影响。

在实现上,RDMA实际上是一种智能网卡与软件架构充分优化的远端内存直接高速访问技术,通过将RDMA协议固化于硬件(即网卡)上,以及支持Zero-copy和Kernel bypass这两种途径来达到其高性能的远程直接数据存取的目标。 使用RDMA的优势如下: :::info

  • 零拷贝(Zero-copy) - 应用程序能够直接执行数据传输,在不涉及到网络软件栈的情况下。数据能够被直接发送到缓冲区或者能够直接从缓冲区里接收,而不需要被复制到网络层。
  • 内核旁路(Kernel bypass) - 应用程序可以直接在用户态执行数据传输,不需要在内核态与用户态之间做上下文切换。
  • 不需要CPU干预(No CPU involvement) - 应用程序可以访问远程主机内存而不消耗远程主机中的任何CPU。远程主机内存能够被读取而不需要远程主机上的进程(或CPU)参与。远程主机的CPU的缓存(cache)不会被访问的内存内容所填充。
  • 消息基于事务(Message based transactions) - 数据被处理为离散消息而不是流,消除了应用程序将流切割为不同消息/事务的需求。
  • 支持分散/聚合条目(Scatter/gather entries support) - RDMA原生态支持分散/聚合。也就是说,读取多个内存缓冲区然后作为一个流发出去或者接收一个流然后写入到多个内存缓冲区里去。 ::: 在具体的远程内存读写中,RDMA操作用于读写操作的远程虚拟内存地址包含在RDMA消息中传送,远程应用程序要做的只是在其本地网卡中注册相应的内存缓冲区。远程节点的CPU除在连接建立、注册调用等之外,在整个RDMA数据传输过程中并不提供服务,因此没有带来任何负载。

    RDMA 三种不同的硬件实现

    RDMA作为一种host-offload, host-bypass技术,使低延迟、高带宽的直接的内存到内存的数据通信成为了可能。目前支持RDMA的网络协议有:
  1. InfiniBand(IB): 从一开始就支持RDMA的新一代网络协议。由于这是一种新的网络技术,因此需要支持该技术的网卡和交换机。

2.RDMA过融合以太网(RoCE): 即RDMA over Ethernet, 允许通过以太网执行RDMA的网络协议。这允许在标准以太网基础架构(交换机)上使用RDMA,只不过网卡必须是支持RoCE的特殊的NIC。

互联网广域RDMA协议(iWARP): 即RDMA over TCP, 允许通过TCP执行RDMA的网络协议。这允许在标准以太网基础架构(交换机)上使用RDMA,只不过网卡要求是支持iWARP(如果使用CPU offload的话)的NIC。否则,所有iWARP栈都可以在软件中实现,但是失去了大部分的RDMA性能优势。

总结

  • 减少了中断次数。
  • 减少了内存拷贝次数
  • 绕过了linux的协议栈,进入用户协议栈,用户获得了协议栈的控制权,能够定制化协议栈降低复杂度
  • 内核栈转移至用户层增加了开发成本.
  • 低负荷服务器不实用,会造成内核空转

    mysql云服务遇到的问题

    RDS for mysql遇到的问题

  • 实例数据量太大,单实例几个TB的数据,这样即使使用xtrabackup物理备份,也需要很长的备份时间,且备份期间写入量大的话可能导致redo日志被覆盖引起备份失败;

  • 大实例故障恢复需要重建时,耗时太长,影响服务可用性(此时存活节点也挂了,那么完蛋了)。时间长有2个原因,一是备份需要很长时间,二是恢复的时候回放redo也需要较长时间;
  • 大实例做只读扩展麻烦,因为只读实例的数据是单独一份的,所以也需要通过备份来重建;
  • RDS实例集群很大,包括成千上万个实例,可能同时有很多实例同时在备份,会占用云服务巨大的网络和IO带宽,导致云服务不稳定;
  • 云服务一般使用云硬盘,导致数据库的性能没有物理机实例好,比如IO延时过高;
  • 主库写入量大的时候,会导致主从复制延迟过大,semi-sync/半同步复制也没法彻底解决,这是由于mysql基于binlog复制,需要走完整的mysql事务处理流程。
  • 对于需要读写分离,且要求部署多个只读节点的用户,最明显的感觉就是每增加一个只读实例,成本是线性增长的。