NDB 集群内部  /  NDB 集群启动阶段  /  STTOR 阶段 1

5.4 STTOR 阶段 1

这是大多数内核块参与的阶段之一(参见 第 5.3 节,“STTOR 阶段 0” 中的表格)。否则,大多数块主要参与数据的初始化,例如,这是 DBTC 所做的一切。

许多块在阶段 1 中初始化对其他块的引用。 DBLQH 初始化对 DBTUP 的块引用,DBACC 初始化对 DBTUPDBLQH 的块引用。DBTUP 初始化对 DBLQHTSMANLGMAN 块的引用。

NDBCNTR 初始化一些变量并设置对 DBTUPDBLQHDBACCDBTCDBDIHDBDICT 的块引用;这些在使用 NDB_STTOR 信号对这些块进行特殊启动阶段处理时是必需的,节点启动过程的大部分实际上是在这里进行的。

如果集群配置为锁定页面(即,如果 LockPagesInMainMemory 配置参数已设置),则 CMVMI 处理此锁定。

QMGR 块调用 initData() 方法(在 storage/ndb/src/kernel/blocks/qmgr/QmgrMain.cpp 中定义),其输出由 READ_CONFIG_REQ 阶段中的所有其他块处理(参见 第 5.1 节,“初始化阶段(阶段 -1)”)。在这些初始化之后,QMGRDIH_RESTARTREQ 信号发送到 DBDIH,它确定是否存在的系统文件;如果存在,则不会执行初始启动。在接收到此信号后,是将节点集成到集群中其他数据节点的过程,其中数据节点一个接一个地进入集群。第一个进入的节点成为主节点;每当主节点死亡时,新的主节点始终是运行时间最长的节点(在剩余的节点中)。

QMGR 设置计时器,以确保在集群中包含的时间不会超过集群配置所允许的时间(有关相关配置参数,请参见 控制超时、间隔和磁盘分页),之后,与所有其他数据节点的通信建立起来。此时,CM_REGREQ 信号将发送到所有数据节点。只有集群的主节点会响应此信号;主节点一次允许一个节点进入集群。如果在 3 秒内没有节点响应,那么主节点成为主节点。如果多个节点同时启动,那么节点 ID 最低的节点成为主节点。主节点在响应此信号时会发送 CM_REGCONF,但也会向当前处于活动状态的所有节点发送 CM_ADD 信号。

接下来,启动节点向所有当前处于“活动状态”的数据节点发送 CM_NODEINFOREQ 信号。当这些节点接收到该信号时,它们会向已连接到它们的 API 节点发送 NODE_VERSION_REP 信号。每个数据节点还会向主节点发送一个 CM_ACKADD,以通知主节点它已经收到了来自新节点的 CM_NODEINFOREQ 信号。最后,每个当前数据节点都会发送 CM_NODEINFOCONF 信号来响应启动节点。当启动节点接收到所有这些信号后,它还会向主节点发送 CM_ACKADD 信号。

当主节点接收到所有预期的 CM_ACKADD 信号时,它知道所有数据节点(包括刚启动的最新节点)都已经回复了 CM_NODEINFOREQ 信号。当主节点接收到最后的 CM_ACKADD 时,它会向所有当前数据节点(即,除了刚启动的节点)发送 CM_ADD 信号。在收到此信号后,现有的数据节点将启用与新节点的通信;它们开始向其发送心跳,并在心跳协议使用的邻居列表中包含新节点。

start 结构将被重置,以便它可以处理新的启动节点,然后每个数据节点会向主节点发送 CM_ACKADD,之后主节点将在接收到所有此类 CM_ACKADD 信号后,向启动节点发送 CM_ADD。然后,新节点将打开其所有与已连接到集群的数据节点的通信通道;它还会设置自己的心跳结构并开始发送心跳。它还会发送 CM_ACKADD 消息来响应主节点。

启动数据节点、已处于“活动状态”的数据节点、主节点以及在该阶段连接到集群的任何 API 节点之间的信号在以下图表中显示。

Exchange of signals in cluster STTOR start phase 1

作为最后一步,QMGR 还会启动它负责的计时器处理。这意味着它会生成一个信号发送到请求它的块。即使任何一个信号实例被延迟,此信号也会每秒发送 100 次。

BACKUP 内核块也会定期开始发送信号。这样可以确保不会向磁盘写入过多的数据,并且数据写入保持在集群配置文件中在重启期间和之后指定的数据写入限制范围内。 DBUTIL 块初始化事务标识,DBTUX 创建对 DBTUP 块的引用,而 PGMAN 初始化指向 LGMANDBTUP 块的指针。 RESTORE 内核块创建对 DBLQHDBTUP 块的引用,以便在需要时能够快速访问这些块。