随着移动互联深入日常生活的各个环节,特别是AI相关业务的广泛部署,实时产生的数据量呈现爆炸式地增长,同时人们对服务响应的速度要求也越来越高。为了更快的处理相关的数据以快速响应用户的请求,在边缘侧部署高性能“全闪存”(在所有数据路径上运行NVMe访问协议,如前端以NVMe-oF接口对外提供服务,后端则直接访问高性能的NVMe存储介质)存储集群的需要也呼之欲出。在边缘侧部署的存储集群通常规模不是很大,但一般会有多节点来实现高可用的需求(如常见的2~3个节点)。
图1. 基于NTB的边缘存储集群组网示意图(节点间基于千兆以太网的管理网络未画出)
NTB传输接口的封装---- RDMA Over NTB
考虑到传统RDMA接口已经被广泛地集成和应用于存储系统的跨节点数据传输中(例如SPDK NVMe-oF Target[2], 在很早的时候就已经支持RDMA作为其传输层),此处介绍的使用NTB传输通道来实现数据传输的方式,没有采用全新的接口,而是基于RDMA的接口框架针对NTB做了相对应的实现----RDMA Over NTB。这样,原有基于RDMA接口开发的应用,可以无缝地切换到NTB通道上运行。
在RDMA Over NTB实现中,一个NTB设备被封装模拟成了一个RDMA的设备使用,也即一个系统下有多少NTB设备就可以提供多少个模拟的RDMA设备。概述而言,RDMA Over NTB主要由3部分组成:
其一,等价于原RDMA用户态verbs库的动态库(libibverbs.so和librdmacm.so),被具体的APP应用链接,运行于APP应用的进程上下文;
其二,用户态的守护进程,负责管理NTB的传输通道并与APP应用进程中链接的库对接实现数据的收发(其存在主要是为了更好地支持多应用程序进程同时共享访问NTB设备,对于APP应用程序为单进程的场景这个守护进程可以选择不要,其相应的逻辑直接合并到前述的动态库中);
其三,内核模块,主要负责申请并映射NTB传输通道buffer到用户态,以及在有用户态守护进程存在时,负责将APP应用进程中用于数据收发的buffer(RDMA 通过MR---- memory region注册的buffer)映射到守护进程,以消除数据收发时APP应用进程和守护进程间的跨进程拷贝。
在有守护进程的模式下,RDMA Over NTB的软件逻辑架构可以概述如图2所示。此种情况下,若以SPDK NVMe-oF Target作为APP应用程序,则相应的RDMA Over NTB的应用场景对应可如图3所示。
图2. RDMA Over NTB软件逻辑架构示意
图3. 以SPDK Target作为应用程序使用RDMA Over NTB时的情况示意(有守护进程)
RDMA Over NTB 可以支持RDMA传统的RC (Reliable Connection) 、UC (Unreliable Connected) 和UD (Unreliable Datagram) 传输类型,其中对于RC类型 CM (Connection Management) 特性的支持是基于TCP socket来实现具体的链接管理操作(复用存储集群的千兆管理网络)。当然,也可以基于NTB的传输通道来实现CM的连接管理。但相对而言基于TCP实现连接管理的功能可以简化相应的实现,并且能将链接管理和NTB传输通道的管理区分开,能更灵活地支持实现和业务相关的调度策略。
此外,RDMA Over NTB的数据的传输完全在用户态完成,且在各个节点上对于一次具体的数据传输(如发送或者接收)仅涉及一次数据的拷贝(类比传统RDMA网卡工作时的DMA)。NTB传输通道的buffer分为Tx和Rx两个部分,被映射到用户态后,以Ring Pair(队列对)的方式被使用,可参见图4所示的情况。每个方向上的buffer被切分成固定大小的单元,每个单元分为 “报头” 和载荷区域。考虑到NTB传输通道的稳定可靠,上层应用通过WR (Work Request) 下发的请求被处理时,发送侧根据WR填充 “报头” 并将具体待传输的用户数据拷贝到Tx Buffer对应的单元中,然后更新队列的下标,随即认为发送完成,不需要专门等待对端的回应;接收侧则根据队列下标的变化从队列中取出相应的数据并进行进一步的处理。这样的设计减少了两端的交互次数,从而极大的提升了数据传输的效率。如此简单的交互逻辑,一方面是基于NTB稳定可靠的传输条件,其涉及的故障场景除Linkdown外基本没有其他的情况; 另一方面则是针对异常的情况可以比较容易从应用层进行处理。目前对于异常处理,主要是监测了NTB的Linkdown事件,当出现NTB传输通道断开时,会通过RDMA的异步事件通道进行上报。因而,只要应用层能缓存NTB传输通道buffer队列深度这么多个最近发送的请求,就可以保证数据在NTB Linkdown情况出现时的数据完整性---- 比如在NTB linkup时,再重新执行这部分最后缓存的请求即可。
图4. NTB 传输通道buffer映射到用户态后的使用方式示意
基于NTB的数据传输主要开销在于应用数据到NTB传输buffer的拷贝,针对这个操作,当前Intel CPU提供的DSA (Data Streaming Accelerator) 功能可以用来释放对CPU的消耗,从而进一步提升性能。
RDMA Over RDMA与SPDK NVMe-oF Target 的结合应用
很早以前RDMA就已经是SPDK NVMoF Target所支持的传输类型,因而SPDK可以很容易和这里描述的RDMA Over NTB进行结合应用。SPDK NVMe-oF Target通常是作为单进程来使用,因而与RDMA Over NTB进行结合使用时,实际也可以不需要守护进程的存在。这样可以省去守护进程所需占用的CPU核,同时也可以避免应用进程核守护进程间存在的一些跨进程交互(主要是控制面的数据),从而进一步提升性能。此种情况下,以SPDK作为应用程序使用RDMA Over NTB的相应情况可如图5所示。
图5. 以SPDK作为应用进程使用RDMA Over NTB的情况示意(无守护进程)
在图5所示的这种使用场景中,可以给每个SPDK使用的CPU核绑定一个独立的NTB传输通道,这样既能方便于与SPDK “Run to Complete” 分核免锁的编程模型相匹配,同时也能更好地实现性能随着SPDK可使用CPU核的增加而线性扩展(使用的CPU核的数量不超过NTB传输通道的数量)。
具体测试时,需要先加载Linux内核自带的ntb驱动相关的模块,然后再插入前文提到的rdma-ntb对应的模块。另外,启动SPDK NVMe-oF target及initiator程序前,需要以执行命令“export LD_LIBRARY_PATH=xxx”的方式来指定RDMA Over NTB对应替换标准RDMA verbs库的用户态库路径,从而target和initiator程序启动时链接的就是新提供的基于NTB传输通道进行实现的verbs库。
按图5所示的场景,在相同环境上对SPDK NVMe-oF Target分别使用RDMA Over NTB和100G TCP的情况进行测试的初步数据对比可如下表1所示。
表1. SPDK NVMe-oF Target分别使用RDMA Over NTB和 100G TCP时的性能对比
此处的对比数据中当前只展示了一个NTB传输通道时的情况,并且未使用DSA的功能。从表中数据可以看到单个NTB的传输通道很容易就将target侧一个CPU核打满了,而跑TCP时,需要4条TCP链接才能打满target侧的一个CPU核,并且时延比NTB时大很多。这初步的数据表明,使用RDMA Over NTB时,单核的性能效率较TCP有很大的提升。
后续将进一步测试多NTB传输通道、DSA使能对性能提升及与真实RDMA卡的性能进行对比的情况。可预见的是,在多NTB传输通道和DSA功能使用的情况下,SPDK NVMe-oF Target使用RDMA Over NTB所带来的的性能效率优势将更为明显。
后续展望
从SPDK NVMe-oF Target使用RDMA Over NTB的应用案例,可以看到使用NTB加速边缘存储集群节点间的数据传输在成本和性能上都有较大的优势,是一个比较好的选择。 不仅如此,单就RDMA Over NTB的接口和框架而言,其可以适配和使用的应用及场景还可以有很多,只要是基于RDMA开发的应用,在小规模组网(如2~3节点)时均可以较好的使用。而具体从NTB与SPDK NVMe-oF Target相结合的这个使用场景而言,将NTB直接实现成一种诸如RDMA/TCP之类的传输层,或许也会有更高性能和效率。相关涉及的应用场景和模式较多,如对此感兴趣,欢迎进一步联系讨论。
参考信息
[1].https://events.static.linuxfound.org/sites/events/files/slides/Linux%20NTB_0.pdf
[2].https://spdk.io/doc/nvmf.html, SPDK NVMe-oF Target User Guide
转载须知
推荐阅读
SPDK vhost-user结合SPDK NVMe-oF RDMA性能调优参考
使用SPDK lib搭建自己的NVMe-oF Target应用
往期阅读
SPDK FIO Bdev Plugin支持RPC,让资源管理面更容易