摘要:从倒退历程到通信模型设计,到你理解一下 GaussDB 通信原理常识。
* MPPDB 通信库倒退历程
- Postgres-XC
办法:采纳 libpq 通信库实现 CN 和 DN 之间的连贯,CN 负责计算,DN 仅进行数据存储。
毛病:随着计算工作的一直增大,CN 计算呈现瓶颈,且白白浪费 DN 的计算能力。
- V1R3
办法:提出分布式执行框架,将计算下推到 DN 上执行,DN 不仅作为存储同时承当计算工作。因为每个 DN 只存储有一部分数据,因而 DN 间也须要进行通信,采纳 stream 线程 TCP 直连,每个连贯都须要一个 TCP 端口。
毛病:随着集群规模的减少,DN 之间的连接数一直减少,在大并发场景下须要大量的 TCP 端口,而理论状况是因为单机 TCP 端口只有 65535 个,TCP 端口数重大限度了数据库的集群规模和并发规模。
- V1R5-V1R7C00
办法:联合 SCTP 协定的多流长处,DN 间的通信采纳 SCTP 通信库架构,应用逻辑连贯来代替物理连贯,用来解决 DN 之间连贯太多的问题。
毛病:SCTP 协定自身存在的内核 BUG,通信报错。
- V1R7C10
办法:TCP 代理通信库。
毛病:CN 和 DN 之间的物理连接数也会暴涨。
- V1R8C00
办法:CN 和 DN 之间也采纳逻辑连贯实现,即 CN 多流。
问题 1:DN 间是查问后果的通信还是原始数据的通信?
解:既有查问后果,也有原始数据;DN之间的数据交换是 Hash 之后,各个 DN 依据所需获取。
* 通信模型的设计
- Pooler 通信模型
问题 2:连接池上的CN、DN 是否存在交加,即 poolA 中的 DN 在poolB中也存在?
解:不存在。
问题 3:CN 和CN的连贯是做什么的?为什么设计连接池连贯 CN 上的 PG 线程?CN上为什么有多个 PG 线程,有什么用处?
解:CN和 CN 之间连贯是为了数据同步等,包含建表之后的信息交汇。CN上的 PG 线程也是为了用户查问建设。
问题 4:DN 上为什么有多个 PG 线程,有什么用处?
解:一个查问操作就是创立一个新的 PG 线程。
问题 5:如何了解gsql 客户端退出时,只退出 PG 线程和 agent 代理线程,而取到的 slot 连贯会还回database pool?
解:slot连贯退回到pooler,下次连贯能够间接获取,若不存在,则从新创立。
问题 6:DN 间的 TCP 连接数:C = (H D Q S) D,为什么最初乘以 D,而不是(D – 1)/ 2 ? 此外,这个公式是否存在高反复,每次查问都要建设 DN 间的通信,而不思考重复性?DN** 间的通信线程数量是否有限度?
解:数据是双向通信,但执行算子是单向的,所以不能除以2。数量有限度,但能够调整。
- DN 间 stream 线程通信模型
执行打算须要应用多个线程进行执行,包含 1 个 CN 线程和每个 DN 上 3 个线程 t1-t3。每个 DN 节点都有 3 个线程是因为数据是散布到每个 DN 上的,在执行查问过程中,查问的每个阶段每个 DN 都要参加。自下而上是数据流,自上而下是控制流。具体执行过程如下:
- 每个 DN 的 t3 程序扫描 table 表,将表数据播送到所有 DN 的 t2 线程;
- 每个 DN 的 t2 接管 t3 的数据,建设 hash 表,而后扫描 store_sales 数据与 customer 表进行 hashjoin,join 后果进行哈希汇集后,重散布发送到对应 DN 的 t1 线程;
- 每个 DN 的 t1 线程将收到的数据进行第二次哈希汇集,排序后将后果传输到 CN;
- CN 收集所有 DN 的返回数据,作为后果集返回。
问题 7:DN 上是否执行查问操作?DN播送的数据是否属于同一个数据表?每个 DN 都播送数据,那最初所有 DN 的数据是否雷同?图中 t2 发送给所有 DN 的t1?、
解:执行,DN上存的数据是表的几分之几,不是整个表,也不是一个表的局部,是所有表的一部分,这样做是为了并发。DN数据不雷同,因为各取所需。
· SCTP 通信库设计
- 概要
- SCTP 协定:一种牢靠、保序协定,反对 message-based 模式,单个通道反对 65535 个流,且多流之间互不阻塞,利用该个性,能够突破设施物理连接数对大规模集群节点间通信的限度,反对更大规模的节点规模。
- 通道共享:每两个节点之间有一个数据传输单向 SCTP 物理通道, 在这条物理通道外部有很多逻辑通道(inner Stream),每个 stream 流由 producer 发送到 consumer,利用 SCTP 外部反对多流的个性,不同的 producer & consumer 对应用通道中不同的流(SCTP 流),因而每两个点之间仅须要两个数据连贯通道。
- 通道复用:查问实现后,物理通道中的逻辑连贯敞开,物理连贯不敞开,前面的查问持续应用建好的物理连贯。
- 流量管制:采纳 pull 模式,因为 SCTP 通道的所有流共享内核的 socket buffer, 为了防止一个连贯发的数据量过大,consumer 端却不接管,导致 kernel 的 buffer 被填满, 阻塞了其余流的发送, 减少了流控, 给每个流设置一个 quota, 由接收端调配,当有 quota 时,告知发送端可发送数据,发送端依据发来的 quota 值,发送 quota 大小的数据量,实现接收端与发送端同步控制;为了保障管制信息的可靠性,将管制信息和数据通道拆散,流控信息走独自的一条双向 TCP 管制通道。
- 架构
- TCP Channels:TCP 管制通道,管制流走此通道;
- SCTP Channels:SCTP 数据通道,蕴含很多 stream 流,数据流走此通道;
- Send Controller 发送端流控线程:gs_senders_flow_controller(),收发管制音讯;
- Recv Controller 接收端流控线程:gs_receivers_flow_controller(),接收端用于发送和接管管制报文,与代理接管线程不同,代理接管线程接管的是数据,而接管流控线程接管的是报文;
- Receiver 代理接管线程:gs_receivers_loop(),用于接收数据的线程,从 sctp 数据通道中接收数据,将数据放到不同逻辑连贯的不同 cmailbox 报箱中,并告诉执行层的 consumer 工作线程来取,取走后,有闲暇的 buffer 时,接收端流控线程会通过 tcp 管制通道告诉发送端还有多少闲暇内存,即还有多少 quota 可用于持续接收数据;
- Auxiliary 辅助线程:gs_auxiliary(),由 top consumer,每个两秒检查一下,解决公共事务,如 DFX 音讯,Cancel 信号响应等;
- 数据 PULL 模型:每个逻辑连贯有 quota 大小的 buffer,须要数据时将闲暇 buffer 的大小(即 quota)发送给发送端,发送端即能够发送 quota 大小的数据,quota 有余时阻塞发送,直到接收端的 buffer 被利用取走。
* TCP 多流实现
TCP 代理在现有的逻辑连贯、代理散发、quota 流控等实现的根底上,将数据通道从 SCTP 协定替换成 TCP 协定,TCP 代理逻辑连贯的实现基于 head+data 的数据包收发模型,在 head 中写入逻辑连贯 id 及后续 data 的长度。
问题 8:单机TCP 只有 65535 个端口,SCTP呢?TCP多流和 TCP 在端口上的区别?TCP的三次握手是否仍旧?
SCTP 是基于音讯流传输,数据收发的最小单位是音讯包(chunk),一个 SCTP 连贯(Association)同时能够反对多个流(stream),每个流蕴含一系列用户所需的音讯数据(chunk)。而 TCP 协定自身只能反对一个流,因而咱们须要在这一个流中辨别不同逻辑连贯的数据,通过在 TCP 报文的 head 中写入逻辑连贯 id 及后续 data 的长度来辨别,这样尽管 TCP 只有一个数据包组成,但每个数据包蕴含多个块,实现了 TCP 的多流。同时发送时需保障整包原子发送。
问题 9:如何多流?是多个通道同时发送head+data 吗?
解:一个流发送残缺的数据。多流是并发。
TCP 代理通信库的发送端实现,producerA 和 producerB 别离给 DN1 发送数据,为保障发送端 head+data 发送的完整性,producerA 首先须要对单个物理连加锁,此时 producerB 处于等锁状态,producerA 将数据残缺发送到本地协定栈后返回,并开释锁,producerB 取得锁后发送数据。节点数越多抵触越少。
问题 10:加锁期待是否影响效率?SCTP 的实现也是如此?
解:不影响,因为有缓存buffer。
问题 11:数据失落,永远无奈达到head 怎么办?始终缓存?
解:不会失落,TCP协定有保障。
* CN 多流实现
在 V1R8C00 版本中,CN 和 DN 之间的链接应用 libcomm 通信库,即两个节点间仅存在一条物理通道,在该物理通道上应用逻辑连贯通道实现并行通信。
- CN 端流程:
- 建设连贯:CN 调用 Libcomm 的 gs_connect 与 DN 建设连贯,入参中指明建设双向逻辑通道,应用雷同的 nidx,sidx 同时初始化发送和承受的 mailbox,通过发送流控线程告诉接收端;
- 期待 DN 返回后果:通过判断发送 mailbox 的状态,确认 DN 端已胜利建设的逻辑连贯(发送流控线程收到 DN 端的 CTRL_READY 报文);
- 发送 startuppacket:通过 PQbuildPGconn,初始化 libpq 的 pg_conn 构造体,生成 startuppacket,随后通过 gs_send 发送 startuppacket 给 DN 端;
- 期待 DN PG 线程初始化:通过 LIBCOMMgetResult,期待 DN 端返回 ready for query 报文,之后认为连贯建设胜利。
- DN 端流程:
- 初始化发送、接管 mailbox:DN 端接管流控线程辨认到连贯申请来自 CN 后,调用 gs_build_reply_conntion,注册 CN 的信息,初始化发送 mailbox,随后初始化接管 mailbox,最终通过流控线程返回 CTRL_READY 报文,示意逻辑通道建设胜利;
- 创立 unix domain sock:DN 端接管流控线程,创立一个 unix domain sock,将生成的逻辑连贯地址通过该通道发给 postmaster 主线程;
- fork postgres 子线程:postmaster 主线程的 serverloop 监听到 unix domain sock 后,接管逻辑连贯地址,保留到 port 构造体中,随后 fork postgres 子线程(沿用原有逻辑);
- postgres 线程初始化结束:在 pg 线程实现初始化后,首先给 CN 回复 ready for query 报文,随后进入 ReadCommand 函数,期待 CN 发来的下一个 Query。
本文分享自华为云社区《GaussDB 通信原理总结》,原文作者:Caesar.D 发。
点击关注,第一工夫理解华为云陈腐技术~