1 阿里如何进行RDMA部署
1.1 RDMA部署规划中的考虑因素
存储集群的部署规划控制着网络拓扑结构、RDMA通信范围、存储节点配置等,必须考虑多种因素,包括存储容量与需求的匹配、硬件成本的控制、性能的优化、可用性和SLA风险的最小化。最终的结果是所有这些因素之间的权衡。
例如,微软部署RDMA的规模是适用于整个CLOS网络。因此,如果不加以阻止,PFC风暴可能会蔓延到整个网络,并导致整个集群的崩溃。在生产级存储系统中,这种风险是不可接受的。
1.2 盘古的RDMA部署选择
RDMA部署所采用的关键原则是可用性优先。
网络和节点配置。图2显示了盘古基于CLOS的网络拓扑结构。与常见的dual-home实践相一致,我们部署了Mellanox CX系列双端口RNIC来连接带有两个不同ToR交换机的主机。特别是,两个物理端口绑定到一个IP地址。网络连接(例如RDMA中的QP)以循环方式(Round-Robin)在两个端口上进行均衡。当一个端口关闭时,可以将此端口上的连接迁移到另一个端口。
表1报告了25Gbps和100Gbps RNIC存储节点的典型硬件配置。每个节点的SSD数量由RNIC总带宽与单个SSD的吞吐量决定,允许I/O吞吐量与网络带宽相匹配。请注意,25Gbps和100Gbps配置中的SSD类型是不同的,这会导致不成比例的数字。计算和存储节点部署在单个podset中的不同机架中。然后根据计算需求计算出计算节点数和存储节点数。
RDMA范围。为了最小化故障域,我们只在每个podset内和存储节点之间启用RDMA通信。计算和存储节点之间的通信通过专用用户空间TCP协议执行。这是由于计算节点的硬件配置复杂,更新速度快。因此,TCP可以有效地作为一种独立于硬件的传输协议来应用。与内核TCP相比,用户空间TCP更便于升级和管理,而内核TCP由于其通用性而被选择用于跨podset通信。
生产部署是podset级RDMA的另一个关注点。在许多数据中心中,podset位于不同的建筑中(跨楼)。对于交叉构建的RDMA链路,基本链路延迟要大得多,而PFC机制需要更大的headroom缓冲区。为了启用RDMA,必须仔细调整和测试Spine交换机上的PFC/ECN阈值。这是一项艰巨的任务,目前还没有取得足够的成果。
RDMA/TCP混合服务。据我们所知,以前关于RDMA部署的研究并没有探讨RDMA和TCP混合服务。在盘古,我们遵循可用性第一原则,将TCP作为最后的手段。尽管目前取得了进展,RDMA设备还远没有完美无缺。因此,当可用性或SLA受到威胁时,将受影响的链路从RDMA切换到TCP可以保持可用带宽。此逃逸计划不会影响未受影响的RDMA链接。
然而,在混合部署过程中,我们确定共存的TCP流量会引发大量TX暂停(即NICs发送的PFC暂停帧),即使RDMA/TCP流量被隔离在两个优先级队列中。表2报告了盘古在不同负载和大约50%TCP流量下的TX暂停生成率。测试在Mellanox CX-4 25Gbps双端口RNIC上执行。如此大量的TX暂停对性能有害,并可能导致PFC风暴。我们与Mellanox一起研究了这个问题,并确定Linux内核中TCP的处理是高度I/O密集型的。内核TCP在NIC的PCIe总线上启动过多的部分写入/偏好性写入(partial writes)。随着PCIe带宽的消耗,NIC的接收管道速度减慢。缓冲区溢出,NIC随后开始传输PFC pause帧。
为了优化TCP的内存访问,我们对数据访问过程进行了一些调整。首先,禁用大接收偏移量(LRO,Large Receive Offset)可以减少内存带宽的使用。这是由于启用LRO时访问多个缓存线造成的。此外,启用NUMA还提高了内存访问的效率,从而有助于减轻PCIe的压力。我们还为RDMA流量在RNIC上分配了更大的缓冲区,以防止TX暂停。最后,使应用程序数据缓存线对齐(cacheline-aligned)也是提高内存效率的常见优化实践。
2 阿里部署RDMA的性能优化
2.1 性能障碍
盘古的性能优化目标是在最大化吞吐量的同时,最大限度地减少延迟。
RDMA-存储协同设计。将RDMA协议栈与存储后端集成是一项挑战。它必须涵盖关键的性能点,如线程建模、内存管理和数据序列化。由于线程之间的通信开销,线程模型直接影响延迟。设计良好的内存管理和数据序列化是在数据访问期间实现零拷贝的关键。在这里,我们将简要介绍这些用于存储目的的组件的设计。
用户空间存储操作系统(USSOS)是一个统一的用户空间存储软件平台,旨在支持NVMe SSD和持久性内存等新的存储介质。其设计原则(例如,内存管理、共享内存机制和用户空间驱动程序)基于众所周知的用户空间技术(例如,DPDK和SPDK)。相关测试显示,在盘古启用USSOS可以将CPU效率平均可提高5%以上。
作为USSOS的核心部分,用户空间存储文件系统(USSFS)是一种为SSD设计的高性能本地文件系统。通过在用户空间中运行,USSFS能够绕过内核以避免用户/内核空间交叉开销。USSOS将磁盘划分为“块”,这些块被ChunkServer在其API中使用(例如,创建、封装和删除)。USSOS直接将数据和元数据写入磁盘,并使用轮询来感知完成事件。对于不同的块大小,与Ext4文件系统相比USSFS能够将IOPS提高4-10倍。
运行到完成(run-to-completion)模型被认为是RDMA网络栈与存储栈集成的最佳方法。这个模型以前在讨论分类存储的研究中被探讨过(例如,Reflex,i10)。然而,这些研究是在2017年将RDMA引入Pangu之后发表的。Reflex和i10侧重于远程直接I/O,而Pangu中的ChunkServer则作为本地存储引擎应用于分布式存储。谷歌的Snap利用一个单独的网络进程来统一网络功能,减少网络连接的数量。
100Gbps网络的内存瓶颈。部署100Gbps网络可以实现更低的延迟和更高的吞吐量。随着网络速度的提高,内存吞吐量成为了系统的瓶颈。
为了获得内存访问吞吐量的上限,我们使用Intel memory Latency Checker(MLC)工具测试内存吞吐量。表3详细说明了硬件资源的实际使用情况。在我们的测试中,最大可实现的内存带宽为61GB/s,读写比为1:1。但是,Pangu工作负载的平均内存吞吐量已经是29GB/s+28GB/s=57GB/s。这表明内存是瓶颈,而不是网络。
通过监视盘古中的内存使用情况,我们确定验证和数据复制过程都需要优化。数据完整性是分布式存储最重要的特性之一。盘古采用循环冗余校验(CRC)进行应用级数据验证。
如图4所示,接收到的数据被分成4KB的块,每个块加上4B CRC值和44B间隙。当计算应用于整个数据集时,此操作是内存和计算密集型操作。数据在写入磁盘时也会被复制,以便包含CRC校验。由于RDMA的远程内存访问语义,在其他组件中不执行复制。
大量QP。我们过去在盘古的运行线程之间采用全网状链路模式(full-mesh link mode),以最大化吞吐量和最小化延迟(图6(a))。假设每个ChunkServer有14个线程,每个BlockServer有8个线程,每个节点同时包含ChunkServer和BlockServer。对于100个存储节点组成的集群中的全网格模式,可能有14个节点×8×2×99=每个节点22176个QPs。由于cache未命中(cache miss),RNICs对于大量QP的性能会急剧下降。特别地,RX暂停(即,接收到的PFC暂停帧)的数目非常高。
以前的研究也证明了同样的问题。为了解决这个问题,FaSST在线程之间共享QPs,由于线程之间QPs的锁争用(lock contention),从而降低了CPU效率和性能。另一种启发式方法是包含一个专用的代理线程来管理所有的接收和发送请求。但是,切换到/从专用代理线程切换回来会增加延迟。此外,单线程很难打满整个网络带宽。此外,代理解决方案对底层RDMA库是不透明的。
2.2 盘古的性能相关设计
盘古的性能相关设计是基于软硬件协同设计的原则,以最小化性能开销。
存储-RDMA统一的运行到完成(Run-to-Completion)协议栈。我们对存储和网络都采用了从运行到完成的线程模型,以实现低延迟。图5示出了用于处理请求的过程。当节点接收到写RPC时,RNIC通过DMA将其发送到用户空间。RPC框架使用轮询获得请求,然后将其交给ChunkServer模块进行处理。然后ChunkServer通知USSFS为请求分配一个“chunk”资源。最后,用户空间驱动程序与NVMe SSD交互以存储数据。这些操作通常在单个服务器线程中执行,而不进行线程切换。这种从运行到完成的模型使延迟最小化。为了减少任务(jobs)造成的阻塞时间,应用程序在提交大的I/O请求时会将请求拆分为小的请求。这种优化确保了对I/O信号的快速响应。针对大型I/O请求的另一种优化策略涉及将辅助工作(例如格式化和CRC计算)传递到非I/O线程,然后在那里对它们进行处理。这些优化将典型存储请求(例如,4KB大小)的平均延迟减少到30us以下。
数据格式统一为I/O向量。在网络中使用分散-聚集DMA(通过单个中断传输不连续数据),通过单个RDMA verb传输I/O向量而不进行复制。由于RDMA语义,序列化是不必要的。
零拷贝和CRC卸载。如上述所述,数据必须在I/O路径上复制一次,因为每个4KB的数据块都经过验证,并附有一个CRC校验值。这里,我们利用RNICs的用户模式内存注册(UMR)特性来避免这种数据复制。UMR可以通过定义适当的内存keys将RDMA数据分散在远程端。因此,可以根据存储应用程序格式格式化和组织数据。我们使用UMR将发送方的连续数据重新映射到接收方的I/O缓冲区,其中包含4KB的数据、4B的校验值和44B的间隔。在CRC计算之后,填充的I/O缓冲区可以直接用于磁盘写入。此外,CRC计算能够卸载到有能力的RNIC(例如Mellanox CX-5),从而降低CPU和内存的使用。4KB数据被发送到RNIC,然后生成4B CRC校验和。
共享链接。我们采用共享链路模式,有效地减少了盘古QP的数量。共享链接模式是在应用层实现的,不影响RDMA库。目的节点中的对应线程被分配给源节点中的每个线程(图6(b))。线程对节点的请求被发送到相应的线程,该线程随后将请求发送到正确的目标线程。
考虑一个有N个线程的守护进程,每个线程轮询N个请求/响应队列以获得请求/响应。请注意,每个请求/响应队列只有一个生产者/消费者。因此,我们对每个请求/响应队列使用无锁队列来避免争用。根据我们的测试,这个设计增加了大约0.3us的延迟。
在共享链接模式下,当源线程发送太多请求时,在请求调度期间,相应线程上会有资源开销。Pangu支持共享组,其中一个节点中的线程可以分为多个组。对应线程只转发对其组成员的请求。回到上一个示例,全共享模式中的QP的数量现在减少到(8+8)×99=1584。如果线程被分成2个共享组,QP的数量将是(8× 2 + 8 × 2) × 99 =3,168.
参考文献:Yixiao Gao, et., al. “When Cloud Storage Meets RDMA”. In Proceedings of USENIX NSDI, 2021.