DolphinDB分布式系统节点间通信协议详解:TCP/IP与RDMA对比分析
DolphinDB分布式系统节点间通信协议详解:TCP/IP与RDMA对比分析
DolphinDB分布式系统支持TCP/IP和RDMA两种节点间通信协议。本文将详细介绍这两种协议的概念、原理与特点,并通过多维度对比为用户给出具体的使用建议。
TCP/IP 协议
TCP/IP协议是互联网中最基本的网络通信模型。它规定了互联网中各部分进行通信的标准和方法,被广泛应用于局域网、城域网、广域网等计算机网络中,可以在各种硬件和操作系统上实现互操作,并且支持异构网络环境。
用户/集群内部连接通过ip和port参数指定传输端口,进而建立TCP/IP连接。根据TCP/IP协议,节点间开始交换数据。在该过程中,将使用DolphinDB自定义的PROTOCOL_DDB协议对数据进行序列化与反序列化。该序列化协议支持最全面的DolphinDB的数据形式和数据类型。此外,在通信过程中,如果发生错误(如数据丢失、连接中断等),节点会采取相应的错误处理机制如重发数据、重新建立连接等。当通信结束或节点需要断开连接时,会执行相应的关闭操作并释放系统资源。
在传输过程中,内部RPC的客户端使用单WSAEventSelect/epoll线程处理事件、通过单独的worker完成数据收发和任务执行,并通过配置参数remoteExecutors控制线程数量;而服务端则使用单WSAEventSelect/epoll线程与worker进行收发,其中通过配置参数workerNum调整常规作业的工作线程的数量。
此外,DolphinDB的TCP/IP协议在套接字(Socket)中封装读写流(DataInputStream接口、DataOutputStream接口),从而实现缓冲区管理,进而避免多次的系统调用。
RDMA 技术
RDMA是一种网络通信技术,它允许计算机系统的内存直接访问其他计算机系统的内存,而无需中央处理单元(CPU)的参与。这种技术可以显著降低通信延迟和CPU负载,凭借零拷贝、内核旁路、协议栈卸载等优势大大提高网络通信的效率和吞吐量。
以下为使用RDMA网卡进行编程操作的两种方式:
- 一种方式是通过Verbs原语,但是这种方式需要修改运行在Socket之上的程序。用户可能需要付出额外的学习与编译成本。
- 另一种常用方法是通过OFED提供的IPoIB高层协议(Upper Layer Protocol)。IPoIB直接把IP报文封装到Infiniband可靠或不可靠的连接上。其中用户态程序依然可以使用Socket进行编程,完全不需要进行改动(需要使用IPoIB所对应的IP地址)。该方法最为简单,但同时可能无法充分发挥RDMA的优势最终导致性能不如预期。
DolphinDB的RDMA技术是在原有的RPC框架之上做了部分修改,在3.00.1版本实现对RDMA Verbs的原生支持。区别于TCP/IP网络架构,RDMA凭借其内核旁路、零拷贝等特性,特别适用于需要高速、低延迟通信的场景,如使用分布式内存表、处理RPC操作等(暂不支持处理流数据)。
原理详解
在传输过程中,客户端使用多个epoll线程,以避免额外的队列和线程切换的开销。由于其只做收发操作,故而不会出现锁、阻塞等操作。通过配置参数remoteExecutors控制线程数量。而在服务端中,使用的则是单WSAEventSelect/epoll线程与worker线程(同样通过workerNum配置)。其中worker同时进行收发和rpc执行操作,以此避免耗时长的任务或者阻塞操作卡住epoll线程。
在缓冲区管理方面,则是把RDMA封装成对外的非阻塞Socket语义,通过直接读写RDMA注册内存,即绕过读写流(DataInputStream接口、DataOutputStream接口),从而避免额外的拷贝。
在内存管理上,通信双方在连接建立阶段预注册私有内存区,运行过程中不再扩张。通信过程中序列化反序列化都通过预注册内存区间分配内存。这种内存管理方式相比于Rendezvous方式内存开销可控,运行过程中也不再有内存注册的开销。序列化反序列化和数据收发之间通过内存所有权的交换从而实现部分零拷贝。
在流控方面则是借鉴了rsocket credit based flow control机制,通信双方在链接建立阶段交换预注册内存大小,按阈值通过RDMA immediate data交换控制信息从而更新credit。这个流控可以直接通过序列化反序列化内存分配反馈给用户,从而避免过多的内存开销。
具体使用
在DolphinDB中配置RDMA功能:
- 在使用前,由于RDMA技术需要特定的网卡硬件支持,建议用户考虑RDMA网卡与现有硬件的兼容性、确保当前的操作系统和驱动程序安装正确。
- 在使用时,请确保已在当前机器中下载依赖的libibverbs库,并且在当前的所有节点(包括controller、datanode、computenode和agent)的配置中都已通过配置参数enableRDMA启用RDMA功能。否则集群无法正常工作。此外,可直接延用已传入的参数ip和port,且原有代码可以实现完全复用。其中,RDMA协议同样使用PROTOCOL_DDB协议进行数据的序列化与反序列化。
在DolphinDB中使用RDMA功能时,请注意:
- 目前RDMA仅支持Linux系统中集群内部调用RPC(远程过程调用)的情况。
- RDMA暂不支持多网卡选择、网卡端口选择、设置轮询次数和设置RDMA预注册的Buffer大小。
TCP/IP 与 RDMA 的对比
TCP/IP与RDMA在通信机制、数据传输方式、内存访问方式和编程模型等方面存在显著差异。
特性 | TCP/IP | RDMA |
---|---|---|
通信机制 | 面向连接 | RC/RD/UC/UD |
数据传输方式 | 数据拷贝、全双工通信 | 零拷贝、直接内存访问 |
内存访问方式 | 通过操作系统内核 | 绕过操作系统内核 |
编程模型 | Socket API | Verbs API |
- TCP/IP以其广泛兼容性、灵活性和稳定可靠性适用于大多数常规工作负载和通用应用场景。
- RDMA则以其高性能、低延迟和高效数据传输能力,在需要处理大量数据和高性能网络通信的场景中更具优势。
协议混用的情况说明
在以太网/TCP的部署中,用户/集群内部通过参数ip和port建立连接。其中在DolphinDB内部,无论使用的是TCP/IP协议还是RDMA功能都需要先建立TCP连接。
- 如果客户端启用RDMA功能,则当前传输框架将首先通过该TCP连接和服务端协商是否使用RDMA协议,以及交换带外数据。若服务端未开启或者不支持RDMA功能,当前连接会由于不支持当前Wire Protocol(线路协议)而报错。
- 如果客户端未启用或不支持RDMA功能,若服务端启用了RDMA功能,则server会自动fallback,并复用已经建立好的连接来完成后续的通信。
具体情况可参见下表。
服务端开启RDMA功能 | 服务端未开启/不支持RDMA功能 |
---|---|
客户端开启RDMA功能 | 可以通信,使用RDMA功能 |
客户端未开启/不支持RDMA功能 | 可以通信,使用TCP/IP协议 |
使用建议
如前文所述,RDMA技术需要特定的网卡硬件支持。
- 在有足够硬件条件支持的情况下,两种协议均可选择使用,但使用RDMA会收获更快的数据传输速度。
- 若无相应硬件条件支持,则仅可使用TCP/IP协议。
简言之,在选择使用哪种通信技术时,需要根据具体的应用需求和网络环境进行综合评估。在有合适硬件支持的情况下,推荐优先使用RDMA。
RDMA 的性能测试案例
内存写入是诸多数据传输操作的基础,其传输速度的提升对数据库的写入、查询和恢复等操作有明显的增效作用。例如,
- 在提交任务、客户端分发数据到数据节点等场景中,当数据以高速率涌入系统时,快速的内存写入能够确保这些数据被及时且准确地存储起来,减少因写入延迟导致的性能瓶颈。
- 再比如在全量查询、Shuffle Join等查询类操作中,快速的内存写入能够确保数据在更新或插入后迅速可用,减少查询时因数据不一致或延迟更新而导致的等待时间。
- 此外,在数据恢复中快速的内存写入同样至关重要。在数据库系统遭遇故障或数据丢失时,高效的内存写入机制能够缩短数据恢复的时间,减少业务中断的影响。
注意:在进行上述操作时,也需要考虑磁盘等其他影响因素。
为方便用户了解RDMA在内存写入方面的性能,以下给出一个简单的测试案例。
测试场景
在某节点创建一个全局内存表。然后在另一个节点通过rpc函数发起查询。通过submitJob控制并发rpc数。测试在真实场景下多少个并发的情况下能够达到100 Gbit/s的带宽(需要的并发数越少越好)。
测试条件
- 内存表shema为10 int,10 long,10 float,10 double,大小大概为3.8 GB。
测试对象
- DolphinDB RPC(IPoIB)
- DolphinDB RPC + RDMA
测试结果
测试结论
由上图可得,RDMA的网卡利用率是IPoIB的两倍。
相关函数和配置参数
运维函数
函数名 | 解释 |
---|---|
getConnections | 获取当前节点的所有网络连接信息:两端IP和端口信息,连接建立时间。 |
配置参数
参数名 | 解释 |
---|---|
tcpNoDelay=true | 启动TCP_NODELAY套接字选项。默认值是false。 |
tcpUserTimeout=300000 | 设置TCP_USER_TIMEOUT套接字选项,单位是毫秒,默认值为300000。 |
lanCluster=true | 集群是否建立在LAN(local area network)上。若为true,心跳采用UDP协议;若为false,心跳采用TCP/IP协议。默认值为true。对部署在云上的集群,应当设为false。 |
dfsChunkNodeHeartBeatTimeout=8 | INT类型,控制节点配置项,用于设置数据节点、计算节点、代理节点心跳超时的临界时间(单位为秒)。若超过该值,控制节点仍未收到对应节点的心跳,则认为该节点已宕机。默认值是8s。 |
maxConnectionPerSite=2 | 从本地节点到远程节点可以创建的最大连接数量。 |
enableRDMA=false | BOOL类型,表示是否开启RDMA。默认值是false,表示不开启。 |