21.6.10 NDB 群集复制:双向复制和循环复制

NDB 群集可以用于两个群集之间的双向复制,也可以用于任意数量的群集之间的循环复制。

循环复制示例. 在接下来的几段中,我们将考虑一个涉及三个 NDB 群集(编号分别为 1、2 和 3)的复制设置示例,其中群集 1 充当群集 2 的复制源,群集 2 充当复制源。群集 3 的源,群集 3 作为群集 1 的源。每个群集都有两个 SQL 节点,其中 SQL 节点 A 和 B 属于群集 1,SQL 节点 C 和 D 属于群集 2,SQL 节点 E 和 E 属于集群 3 的 F。

只要满足以下条件,就支持使用这些群集的循环复制:

  • 所有源和副本上的 SQL 节点都相同。

  • 所有充当源和副本的 SQL 节点都在启用log_slave_updates系统变量的情况下启动。

下图显示了这种类型的循环复制设置:

图 21.48 NDB 群集循环复制,所有源都为副本

周围的文本中描述了一些内容。该图显示了三个群集,每个群集有两个节点。连接不同群集中的 SQL 节点的箭头说明所有源也是副本。

在这种情况下,群集 1 中的 SQL 节点 A 复制到群集 2 中的 SQL 节点 C。 SQL 节点 C 复制到群集 3 中的 SQL 节点 E; SQL 节点 E 复制到 SQL 节点 A。换句话说,复制线(由图中的弯曲箭头指示)直接连接用作复制源和副本的所有 SQL 节点。

也可以通过以下方式设置循环复制:并非所有源 SQL 节点也都是副本,如下所示:

图 21.49 并非所有源都是副本的 NDB 群集循环复制

周围的文本中描述了一些内容。该图显示了三个群集,每个群集有两个节点。连接不同群集中的 SQL 节点的箭头 table 示并非所有源都是副本。

在这种情况下,每个群集中的不同 SQL 节点将用作复制源和副本。您必须不要在启用log_slave_updates系统变量的情况下启动任何 SQL 节点。这种用于 NDB 群集的循环复制方案应该是可行的,其中复制线(再次由图中的弯曲箭头指示)是不连续的,但应注意,它尚未经过全面测试,因此必须仍被认为是实验性的。

使用 NDB 本地备份和还原来初始化副本群集. 设置循环复制时,可以通过在一个 NDB 群集上使用 ManagementClient 端BACKUP命令初始化副本群集,以创建备份,然后应用使用ndb_restore在另一个 NDB 群集上进行此备份。这不会在作为副本的第二个 NDB 群集的 SQL 节点上自动创建二进制日志。为了导致创建二进制日志,必须在该 SQL 节点上发出SHOW TABLES语句;这应该在运行START SLAVE之前完成。这是一个已知的问题。

多源故障转移示例. 在本节中,我们将讨论具有三个具有服务器 ID 1、2 和 3 的 NDB 群集的多源 NDB 群集复制设置中的故障转移。在这种情况下,群集 1 复制到群集 2.和 3;群集 2 也复制到群集 3.此关系如下所示:

图 21.50 具有 3 个源的 NDB 群集多主复制

具有三个具有服务器 ID 1、2 和 3 的 NDB 群集的多源 NDB 群集复制设置;集群 1 复制到集群 2 和 3;群集 2 也复制到群集 3.

换句话说,数据是通过 2 条不同的路径从群集 1 复制到群集 3 的:直接地,以及通过群集 2 的方式。

并非所有参与多源复制的 MySQL 服务器都必须同时充当源和副本,并且给定的 NDB 群集可能将不同的 SQL 节点用于不同的复制通道。这样的情况如下所示:

图 21.51 使用 MySQL 服务器的 NDB 群集多源复制

周围的文本中描述了概念。显示三个节点:群集 1 中的 SQL 节点 A 复制到群集 3 中的 SQL 节点 F;群集 1 中的 SQL 节点 B 复制到群集 2 中的 SQL 节点 C;群集 3 中的 SQL 节点 E 复制到群集 3 中的 SQL 节点 G。群集 1 中的 SQL 节点 A 和 B 具有--log-slave-updates = 0;群集 2 中的 SQL 节点 C 和群集 3 中的 SQL 节点 F 和 G 具有--log-slave-updates = 1;群集 2 中的 SQL 节点 D 和 E 具有--log-slave-updates = 0.

充当副本的 MySQL 服务器必须在启用log_slave_updates系统变量的情况下运行。上图还显示了哪个mysqld进程需要此选项。

Note

使用log_slave_updates系统变量对不作为副本服务器运行的服务器无效。

当其中一个复制群集出现故障时,就需要进行故障转移。在此示例中,我们考虑了以下情况:群集 1 失去了服务,因此群集 3 丢失了群集 1 的 2 个更新源。由于 NDB 群集之间的复制是异步的,因此无法保证群集 3 的更新直接源自群集 1.的更新要比通过群集 2 接收到的更新更早。您可以通过确保群集 3 在群集 1 的更新方面赶上群集 2 来进行处理。就 MySQL 服务器而言,这意味着您需要从 MySQL 复制所有未完成的更新。服务器 C 到服务器 F。

在服务器 C 上,执行以下查询:

mysqlC> SELECT @latest:=MAX(epoch)
     ->     FROM mysql.ndb_apply_status
     ->     WHERE server_id=1;

mysqlC> SELECT
     ->     @file:=SUBSTRING_INDEX(File, '/', -1),
     ->     @pos:=Position
     ->     FROM mysql.ndb_binlog_index
     ->     WHERE orig_epoch >= @latest
     ->     AND orig_server_id = 1
     ->     ORDER BY epoch ASC LIMIT 1;

Note

通过将适当的索引添加到ndb_binlog_indextable 中,可以提高此查询的性能,从而可以显着加快故障转移时间。有关更多信息,请参见第 21.6.4 节“ NDB 群集复制架构和 table”

手动将* @file @pos *的值从服务器 C 复制到服务器 F(或让您的应用程序执行等效操作)。然后,在服务器 F 上,执行以下更改为主语句:

mysqlF> CHANGE MASTER TO
     ->     MASTER_HOST = 'serverC'
     ->     MASTER_LOG_FILE='@file',
     ->     MASTER_LOG_POS=@pos;

完成此操作后,您可以在 MySQL 服务器 F 上发出START SLAVE语句;这会导致任何源自服务器 B 的丢失更新都被复制到服务器 F。

更改为主语句还支持IGNORE_SERVER_IDS选项,该选项采用逗号分隔的服务器 ID 列 table,并使源自相应服务器的事件被忽略。有关更多信息,请参见第 13.4.2.1 节“将主 table 更改为语句”第 13.7.5.34 节“ SHOW SLAVE STATUS 语句”。有关此选项如何与ndb_log_apply_status变量交互的信息,请参见第 21.6.8 节“使用 NDB 群集复制实现故障转移”