在MySQL Cluster中,重新启动是分阶段处理的,节点的重启由一组阶段驱动。此外,节点重启也与已启动的节点以及与我们的节点并行启动的其他节点同步。此注释将描述所使用的各个阶段。
原文
启动节点的第一步是创建数据节点运行时环境。数据节点进程通常使用angel进程运行,此angel进程确保数据节点万一失败时能够自动重新启动。因此,再次运行数据节点的唯一原因是在OS崩溃之后或运营商关闭之后或作为软件升级的一部分。
当启动数据节点时,数据节点需要一个节点id,这是通过设置参数–ndb-nodeid在启动datanode时,或者在检索配置时由管理服务器分配。对于数据节点的所有重新启动,angel进程将确保所分配的节点id将相同。
在分配数据节点进程之后,启动进程保持为angel进程并且新进程成为实际的数据节点进程。实际的数据节点进程首先从managementserver检索配置。
在这个阶段我们已经阅读了选项,我们已经分配了一个节点ID,我们从管理服务器加载了配置。我们将在数据节点日志中打印一些关于我们的线程配置和其他一些重要信息。为了确保我们找到正确的文件并在正确的位置创建文件,我们设置了数据节点进程的数据文件夹。
接下来我们必须启动看门狗线程,因为我们现在开始执行操作,我们希望确保我们不要由于某些软件错误而卡住了。
接下来我们将分配全局内存池的内存,这是分配最多内存的地方,我们仍然有相当多的内存分配,作为NDB内核中各种软件模块初始化的部分,但是我们正在逐步使用全局内存池。
分配内存可能是一个相当耗时的过程,其中操作系统可以为每个分配的GByte内存提供长达一秒的时间(自然是OS依赖的并且会随着时间的推移而变化)。
实际上在这里消耗时间实际上是我们还触摸每个页面以确保分配的内存也被映射到真实物理内存以避免在我们运行该过程时页面未命中。为了加快这个过程,我们已经触及了内存多线程。实际上,大多数内存的分配是可配置的,配置变量LateAlloc
可用于延迟大多数内存分配到重启的早期阶段。
分配全局内存池后,我们初始化运行时环境使用的所有数据。 这可确保我们准备好在数据节点进程启动后立即在线程之间发送和接收数据。
在这一点上,我们只启动了看门狗进程并且线程在创建进程的过程中启动(如果我们运行ndbmtd,这个线程稍后将被转换为第一个接收线程,如果我们正在运行,则该线程将被转换为唯一的执行线程NDBD)。 下一步是加载所有软件模块并初始化它们,以确保在消息开始到达执行时正确设置它们。
在我们启动运行时环境之前,我们还需要激活发送和接收服务。 这涉及创建一个套接字客户端线程,该线程试图连接到集群中其他节点的套接字服务器部分,并创建一个线程来监听用于我们作为套接字服务器通信的那些数据节点的套接字服务器。
默认行为是nodeid最低的节点是通信设置中的套接字服务器。 这可以在数据节点配置中更改。
在我们继续并启动数据节点环境之前,我们将运行时环境的启动信号放在其正确的作业缓冲区中。 实际上,为了启动系统,需要在作业缓冲区中放置两个相等的信号。 第一个启动信号开始与其他节点的通信,并设置状态以等待下一个信号实际启动系统。 第二个将开始运行启动阶段。
最后,我们启动运行时环境的所有线程。 这些当前可以包括主线程,代表线程,多个tc线程,多个发送线程,多个接收线程和多个ldm线程。 鉴于已预先分配了所有线程的通信缓冲区,我们可以在这些线程启动时立即开始发送信号。 接收线程一旦到达其线程启动代码中的那一点就会开始处理其接收到的信号。
有两个相同的启动信号,第一个启动定期发送的重复信号,以跟踪数据节点中的时间。 只有第二个开始执行各种启动阶段。
数据节点的启动在一组阶段中处理。 第一阶段是将信号READ_CONFIG_REQ发送到内核中的所有软件模块,然后将STTOR类似地发送到256个阶段的所有软件模块,编号从0到255.这些模块的编号从0到255,我们不使用全部 这些阶段,但代码是灵活的,以便任何这些阶段可以现在使用或在将来的某个时间使用。
此外,我们还有6个模块,这些模块涉及另外一组启动阶段。 在这些阶段发送的信号称为NDB_STTOR。 最初的想法是将此消息视为NDB子系统的本地启动。 这些信号由NDBCNTR发送和处理,并作为NDBCNTR中STTOR处理的一部分发送。 这意味着它成为启动阶段的连续部分。
在开始阶段之前,我们确保任何管理节点都可以连接到我们的节点,并且所有其他节点都已断开连接,并且它们只能向QMGR模块发送消息。 管理服务器接收关于数据节点中的各种事件的报告,并且QMGR模块负责将数据节点包括在集群中。 在我们被包含在集群中之前,我们无法以任何方式与其他节点通信。
开始总是从主线程开始,其中每个软件模块至少由所有多线程模块包含的代理模块表示。 代理模块使用一条消息和一条回复,可以轻松地向一组相同类型的模块发送和接收消息。
READ_CONFIG_REQ信号始终以相同的顺序发送。 它首先发送到CMVMI,这是接收启动顺序的块,它执行许多功能,软件模块可以从这些功能影响运行时环境。 它通常会分配进程的大部分内存并触及所有内存。 它是主线程的一部分。
接收READ_CONFIG_REQ的下一个模块是NDBFS,这是控制文件系统线程的模块,该模块位于主线程中。
下一个模块是DBINFO,该模块支持ndbinfo数据库,用于以表格格式获取有关数据节点内部的信息,该模块位于主线程中。
接下来是DBTUP,这是存储实际数据的模块。
下一个DBACC,存储主键和唯一键哈希索引的模块以及我们控制行锁的位置。 这两个块都包含在ldm线程中。
接下来是DBTC,即管理事务协调的模块,该模块是tc线程的一部分。 接下来是DBLQH,该模块通过键操作和扫描控制对数据的操作,并且还处理REDO日志。 这是ldm线程的主要模块。
接下来是DBTUX,它操作有序索引重用页面,用于在DBTUP中存储行,也是ldm线程的一部分。 接下来是DBDICT,这是一个字典模块,用于存储和处理有关表和列,表空间,日志文件等的所有元数据信息。 DICT是主线程的一部分。
接下来是DBDIH,用于存储和处理有关所有表,表分区和每个分区的所有副本的分发信息的模块。 它控制本地检查点进程,全局检查点进程并控制重新启动处理的主要部分。 DIH模块是主线程的一部分。
接下来是控制重启阶段的NDBCNTR,它是主线程的一部分。 接下来是QMGR,它负责处理心跳协议以及包含和排除集群中的节点。 它是主线程的一部分。
接下来是TRIX,它执行与有序索引和其他基于触发器的服务相关的一些服务。 它是tc线程的一部分。 接下来是BACKUP,它用于备份和本地检查点,是ldm线程的一部分。
接下来是DBUTIL,它提供了许多服务,例如代表模块中的代码执行密钥操作。 它是主线程的一部分。
接下来是负责复制事件的SUMA模块,这是由rep线程处理的模块。
接下来是TSMAN,然后是LGMAN,然后是PGMAN,它们都是磁盘数据处理的一部分,负责处理表空间,UNDO日志记录和页面管理。 它们都是ldm线程的一部分。
RESTORE是一个用于在启动时恢复本地检查点的模块。 该模块也是ldm线程的一部分。
最后,我们有DBSPJ模块来处理向下推送到数据节点的连接查询,它作为tc线程的一部分执行。
DBTUP,DBACC,DBLQH,DBTUX,BACKUP,TSMAN,LGMAN,PGMAN,RESTORE都是紧密集成的模块,它们在每个节点中本地处理数据和索引。 这组模块形成一个LDM实例,每个节点可以有多个LDM实例,这些实例可以分布在一组线程上。
每个LDM实例都拥有自己的数据分区。 我们还有两个不属于重启处理的模块,这是TRPMAN模块,它执行许多与传输相关的功能(与其他节点通信)。 它在接收线程中执行。 最后,我们有THRMAN在每个线程中执行并执行一些线程管理功能。
所有模块都接收READ_CONFIG_REQ,所有模块也接收STTOR用于阶段0和阶段1.在阶段1中,他们报告他们希望获得更多信息的起始阶段。
在READ_CONFIG_REQ期间,线程可以在模块中执行很长时间,因为我们可以分配和触摸大尺寸的存储器。 这意味着我们的监视程序线程在此阶段有一个特殊的超时,以确保我们不会因为长时间初始化内存而导致进程崩溃。 在正常操作中,每个信号应仅执行少量微秒。
通过将消息STTOR发送到所有模块来同步启动阶段,逻辑上每个模块从0到255获得每个启动阶段的该信号。然而,响应消息STTORRY包含模块真正感兴趣的启动阶段列表。
处理起始相位信号的NDBCNTR模块可以优化掉不需要的任何信号。 模块接收STTOR消息的顺序对于所有阶段都是相同的:
1) NDBFS
2) DBTC
3) DBDIH
4) DBLQH
5) DBACC
6) DBTUP
7) DBDICT
8) NDBCNTR
9) CMVMI
10) QMGR
11) TRIX
12) BACKUP
13) DBUTIL
14) SUMA
15) DBTUX
16) TSMAN
17) LGMAN
18) PGMAN
19) RESTORE
20) DBINFO
21) DBSPJ
此外,还有一个由NDBCNTR控制的特殊启动阶段处理,因此当NDBCNTR收到自己的STTOR消息时,它会启动涉及模块的本地启动阶段处理,DBLQH,DBDICT,DBTUP,DBACC,DBTC和DBDIH。
对于阶段2到8,会发生这种情况。在这些启动阶段发送的消息是NDB_STTOR和NDB_STTORRY,它们的处理方式与STTOR和STTORRY类似。 模块还以相同的顺序接收所有阶段的启动阶段,此顺序为:
1) DBLQH
2) DBDICT
3) DBTUP
4) DBACC
5) DBTC
6) DBDIH
对于那些多线程的模块,STTOR和NDB_STTOR消息始终由在主线程中执行的代理模块接收。 然后,代理模块将STTOR和NDB_STTOR消息发送到模块的每个单独实例(实例数通常与线程数相同,但有时可能不同)。 它并行执行,因此所有实例并行执行STTOR。
因此,有效地,模块的每个实例将在逻辑上首先接收READ_CONFIG_REQ,然后为每个启动阶段接收一组STTOR消息,并且一些模块也将按特定顺序接收NDB_STTOR。 所有这些消息都按特定顺序发送并按顺序发送。 因此,这意味着我们能够通过在正确的启动阶段执行操作来控制何时完成任务。
接下来,我们将逐步描述节点重启(或节点作为集群启动/重启的一部分启动)中发生的情况。 启动目前是一个顺序过程,除非声明它并行发生。 以下描述因此描述了当前实际发生的顺序。