如何在Ubuntu20.04上配置MySQL组复制

来自菜鸟教程
跳转至:导航、​搜索

介绍

MySQL 复制可靠地将数据和操作从一个数据库镜像到另一个数据库。 常规复制涉及配置为接受数据库写入操作的主服务器,辅助服务器将主服务器日志中的操作复制并应用到它们自己的数据集。 这些辅助服务器可用于读取,但通常无法执行数据写入。

组复制是一种实现更灵活、容错的复制机制的方法。 此过程涉及建立一个服务器池,每个服务器都参与确保正确复制数据。 如果主服务器出现问题,成员选举可以从组中选择一个新的主服务器。 这允许其余节点继续运行,即使在遇到问题时也是如此。 通过 Paxos 共识算法 的实现提供成员协商、故障检测和消息传递。

在本教程中,您将使用一组三个 Ubuntu 20.04 服务器设置 MySQL 组复制。 请注意,三个是您在 MySQL 中部署组复制所需的最小 MySQL 实例数,而最多九个。 在学习本教程时,您可以选择将组设置为单主复制组或多主复制组。

注意:数据库服务器在复制设置中可以具有两个角色之一:它们可以是 主实例 (也称为 实例),其中用户可以写入数据; 或 副本 (或 辅助实例 ),它存储源上所有数据的副本。 从历史上看,这些角色分别被称为 主实例从实例 。 在 2020 年 7 月发布的博文 中,MySQL 团队承认该术语的负面来源,并宣布他们努力更新数据库程序及其文档以使用更具包容性的语言。

然而,这是一个持续的过程。 尽管 MySQL 的文档和程序版本 8 中的许多命令已更新,以将复制拓扑中的服务器称为 primary 及其 secondaries(或 [X221X ]source 及其 replicas),有些地方仍然会出现负面术语。 本指南将尽可能默认使用更具包容性的术语,但在某些情况下不可避免地会出现较旧的术语。


先决条件

要完成本指南,您需要:

  • 三台运行 Ubuntu 20.04 的服务器。 每个人都应该有一个具有 sudo 权限的非 root 管理用户和一个配置了 UFW 的防火墙。 按照我们的 Ubuntu 20.04 初始服务器设置指南设置每个服务器。
  • MySQL 安装在每台服务器上。 本指南假定您使用的是默认 Ubuntu 存储库中提供的最新版本的 MySQL,在撰写本文时,该版本是 8.0.28 版。 要在所有服务器上安装它,请按照我们关于 如何在 Ubuntu 20.04 上为每台机器安装 MySQL 的指南进行操作。

为了清楚起见,本指南将三个服务器称为 member1member2member3。 在本指南的示例中,这些成员将具有以下 IP 地址:

成员 IP地址
会员1 203.0.113.1
成员2 203.0.113.2
会员3 203.0.113.3

必须在 member1 上运行的任何命令都将具有蓝色背景,如下所示:


同样,必须在 member2 上运行的任何命令都将具有红色背景:


并且必须在 member3 上运行的任何命令都将具有绿色背景:


最后,任何必须在 三台服务器 中的每台服务器上运行的命令都将具有标准背景:


第 1 步 — 生成 UUID 以识别 MySQL 组

在打开 MySQL 配置文件来配置组复制设置之前,您需要生成一个 UUID,您可以使用它来标识您将创建的 MySQL 组。

member1 上,使用 uuidgen 命令为组生成有效的 UUID:

uuidgen
Output168dcb64-7cce-473a-b338-6501f305e561

复制您收到的值,因为在为您的服务器池配置组名时,您必须稍后引用它。

第 2 步 — 在 MySQL 配置文件中设置组复制

现在您已准备好修改 MySQL 的配置文件。 使用您喜欢的文本编辑器打开 每个 MySQL 服务器 上的主 MySQL 配置文件。 在这里,我们将使用 nano

sudo nano /etc/mysql/my.cnf

在 Ubuntu 上,MySQL 安装了许多不同的文件,您可以使用它们来定义各种配置更改。 默认情况下,my.cnf 文件仅用于从子目录中获取其他文件。 您必须在 !includedir 行的 下方添加您自己的配置 。 这将允许您覆盖包含文件中的任何设置。

首先,通过包含 [mysqld] 标头开始一个新部分,然后添加启用组复制所需的设置,如以下示例中突出显示的那样。 请注意,这些设置是根据 官方 MySQL 文档 中概述的组复制所需的最低设置修改的。 loose- 前缀允许 MySQL 处理它无法正常识别且不会失败的选项。 稍后您将需要填写和自定义其中一些设置

/etc/mysql/my.cnf

. . .
!includedir /etc/mysql/conf.d/
!includedir /etc/mysql/mysql.conf.d/

[mysqld]

# General replication settings
disabled_storage_engines="MyISAM,BLACKHOLE,FEDERATED,ARCHIVE,MEMORY"
gtid_mode = ON
enforce_gtid_consistency = ON
master_info_repository = TABLE
relay_log_info_repository = TABLE
binlog_checksum = NONE
log_slave_updates = ON
log_bin = binlog
binlog_format = ROW
transaction_write_set_extraction = XXHASH64
loose-group_replication_bootstrap_group = OFF
loose-group_replication_start_on_boot = OFF
loose-group_replication_ssl_mode = REQUIRED
loose-group_replication_recovery_use_ssl = 1

# Shared replication group configuration
loose-group_replication_group_name = ""
loose-group_replication_ip_whitelist = ""
loose-group_replication_group_seeds = ""

# Single or Multi-primary mode? Uncomment these two lines
# for multi-primary mode, where any host can accept writes
#loose-group_replication_single_primary_mode = OFF
#loose-group_replication_enforce_update_everywhere_checks = ON

# Host specific replication configuration
server_id = 
bind-address = ""
report_host = ""
loose-group_replication_local_address = ""

为了更清楚地解释所有这些配置选项,它们被分成以下小节。 请仔细阅读它们,因为某些部分会为您提供有关如何部署复制组的选择,或者要求您输入特定于您自己的配置的详细信息。

样板组复制设置

第一部分包含不需要修改的组复制所需的常规设置:

/etc/mysql/my.cnf

. . .
# General replication settings
disabled_storage_engines="MyISAM,BLACKHOLE,FEDERATED,ARCHIVE,MEMORY"
gtid_mode = ON
enforce_gtid_consistency = ON
master_info_repository = TABLE
relay_log_info_repository = TABLE
binlog_checksum = NONE
log_slave_updates = ON
log_bin = binlog
binlog_format = ROW
transaction_write_set_extraction = XXHASH64
loose-group_replication_bootstrap_group = OFF
loose-group_replication_start_on_boot = OFF
loose-group_replication_ssl_mode = REQUIRED
loose-group_replication_recovery_use_ssl = 1
. . .

MySQL 中组复制的一项特殊要求是数据必须存储在 InnoDB 存储引擎中。 MySQL 文档建议明确禁用其他可能导致错误的存储引擎,例如本节中第一行未注释的行。

其余设置打开全局事务 ID,配置组复制所需的二进制日志记录,并为组配置 SSL。 此配置还设置了一些其他有助于恢复和引导的项目。 您无需修改此部分中的任何内容,并且所有三台服务器上的内容都应该相同,因此您可以在添加后继续进行操作。

共享组复制设置

第二部分为组设置共享设置。 您必须自定义一次,然后在每个节点上使用相同的设置。 具体来说,您必须添加群组的 UUID(您在上一步中创建)、授权群组成员列表以及要联系的种子成员,以获取加入群组时的初始数据。

loose-group_replication_group_name 设置为您之前使用 uuidgen 命令生成的 UUID 值。 确保将 UUID 放在空的双引号之间。

接下来,将 loose-group_replication_ip_whitelist 设置为所有 MySQL 服务器 IP 地址的列表,以逗号分隔。 loose-group_replication_group_seeds 设置应该与白名单几乎相同,但应该在每个成员的末尾附加一个指定的组复制端口。 出于本指南的目的,请使用推荐的组复制端口 33061

/etc/mysql/my.cnf

. . .
# Shared replication group configuration
loose-group_replication_group_name = "168dcb64-7cce-473a-b338-6501f305e561"
loose-group_replication_ip_whitelist = "203.0.113.1,203.0.113.2,203.0.113.3"
loose-group_replication_group_seeds = ""203.0.113.1:33061,203.0.113.2:33061,203.0.113.3:33061"
. . .

这部分在每个 MySQL 服务器上应该是相同的,因此请确保在每个服务器上都仔细复制它。

选择单主或多主

接下来,您需要决定是配置 single-primary 还是 multi-primary 组。 在单主配置中,MySQL 指定一个主服务器(几乎总是第一个组成员)来处理写入操作。 多主组允许任何组成员执行写入。

如果您希望配置多主组,请取消注释 loose-group_replication_single_primary_modeloose-group_replication_enforce_update_everywhere_checks 指令。 这将建立一个多主组。 对于单个主要组,只需将这两行注释掉:

/etc/mysql/my.cnf

. . .
# Single or Multi-primary mode? Uncomment these two lines
# for multi-primary mode, where any host can accept writes
#loose-group_replication_single_primary_mode = OFF
#loose-group_replication_enforce_update_everywhere_checks = ON
. . .

这些设置在每个 MySQL 服务器上必须相同。

您可以在以后更改此设置,但在这样做之后,您必须重新启动 MySQL 组的每个成员。 要切换到新配置,您必须停止组中的每个 MySQL 实例,使用新设置启动每个成员,然后重新引导组复制。 这不会影响您的任何数据,但需要一小段停机时间。

特定于主机的配置设置

第四部分包含每个服务器上不同的设置,包括:

  • 服务器标识
  • 要绑定的地址
  • 向其他成员报告的地址
  • 本地复制地址和监听端口

server_id 指令必须设置为唯一编号。 对于第一个成员,将其设置为 1 并增加每个附加主机上的数字。 将 bind-addressreport_host 设置为各自服务器的 IP 地址,以便 MySQL 实例将侦听外部连接并将其地址正确报告给其他主机。 loose-group_replication_local_address 也应该设置为当前服务器的 IP 地址,组复制端口 (33061) 附加到 IP 地址。

例如,以下是 member1 使用其示例 IP 地址的配置的这一部分:

/etc/mysql/my.cnf

. . .
# Host specific replication configuration
server_id = 1
bind-address = "203.0.113.1"
report_host = "203.0.113.1"
loose-group_replication_local_address = "203.0.113.1:33061"

在每个 MySQL 服务器上完成此过程。 以下是 member2 的配置:

/etc/mysql/my.cnf

. . .
# Host specific replication configuration
server_id = 2
bind-address = "203.0.113.2"
report_host = "203.0.113.2"
loose-group_replication_local_address = "203.0.113.2:33061"

以下是 member3 的配置:

/etc/mysql/my.cnf

. . .
# Host specific replication configuration
server_id = 3
bind-address = "203.0.113.3"
report_host = "203.0.113.3"
loose-group_replication_local_address = "203.0.113.3:33061"

请务必将每个突出显示的 IP 地址更新为您正在编辑其配置的服务器的地址。

完成后,请仔细检查每台主机上的共享复制设置是否相同,以及是否为每台主机定制了特定于主机的设置。 完成后保存并关闭每个主机上的文件。 如果您使用 nano 编辑文件,您可以按 CTRL + XY,然后按 ENTER 进行编辑。

您的每个服务器的 MySQL 配置文件现在都包含引导 MySQL 组复制所需的指令。 要将新设置应用于 MySQL 实例,请使用以下命令在 每个服务器 上重新启动服务:

sudo systemctl restart mysql

有了它,您可以通过更新每个服务器的防火墙规则来启用远程访问。

第 3 步 — 更新每个服务器的 UFW 规则

假设您遵循先决条件 初始服务器设置指南 ,您将在每个安装了 MySQL 的服务器上设置防火墙,并启用对 OpenSSH UFW 配置文件的访问。 这是一项重要的安全措施,因为这些防火墙当前阻止与服务器上任何端口的连接,除了 ssh 连接,这些连接提供的密钥与每个服务器各自的 authorized_keys 文件中的密钥一致。

在 MySQL 配置文件中,您将服务配置为在默认端口 3306 上侦听外部连接。 您还将 33061 定义为成员应用于复制协调的端口。

在您的每个成员服务器 上,您需要为该组中的其他成员打开对这两个端口的访问,以便他们都可以相互通信。 要为 member2 打开对 member1 上这些端口的访问,请在 member1 上运行以下 ufw 命令:

sudo ufw allow from member2_server_ip to any port 3306
sudo ufw allow from member2_server_ip to any port 33061

请务必更改 member2_server_ip 以反映您的 member2 服务器的实际 IP 地址。 然后,要为 member3 打开相同的端口,请运行以下命令:

sudo ufw allow from member3_server_ip to any port 3306
sudo ufw allow from member3_server_ip to any port 33061

接下来,更新其他两台服务器的防火墙规则。 在 member2 上运行以下命令,确保更改 IP 地址以分别反映 member1member3 的 IP 地址:

sudo ufw allow from member1_server_ip to any port 3306
sudo ufw allow from member1_server_ip to any port 33061
sudo ufw allow from member3_server_ip to any port 3306
sudo ufw allow from member3_server_ip to any port 33061

最后,在 member3 上运行这两个命令。 同样,请确保为每台服务器输入正确的 IP 地址:

sudo ufw allow from member1_server_ip to any port 3306
sudo ufw allow from member1_server_ip to any port 33061
sudo ufw allow from member2_server_ip to any port 3306
sudo ufw allow from member2_server_ip to any port 33061

添加这些 UFW 规则后,您的三个 MySQL 实例中的每一个都将被允许访问其他两台服务器上 MySQL 使用的端口。

打开对 MySQL 端口的访问后,您现在可以创建复制用户并启用组复制插件。

第 4 步 — 配置复制用户并启用组复制插件

为了与复制组中的其他服务器建立连接,每个 MySQL 实例必须有一个专用的复制用户。

每个 MySQL 服务器 上,以管理用户身份登录到您的 MySQL 实例以启动交互式会话:

sudo mysql

注意:请务必在您的每个 MySQL 实例上运行本节 中的每个命令。


因为每台服务器都会有自己的复制用户,所以需要在创建过程中关闭二进制日志。 否则,一旦复制开始,该组将尝试将复制用户从主服务器传播到其他服务器,从而与已经存在的复制用户产生冲突。 在每个服务器 上的 MySQL 提示符 运行以下命令:

SET SQL_LOG_BIN=0;

现在您可以运行 CREATE USER 语句来创建您的复制用户。 运行以下命令,创建名为 repl 的用户。 此命令指定复制用户必须使用 SSL 进行连接。 此外,请确保在创建此复制用户时使用安全密码代替 password

CREATE USER 'repl'@'%' IDENTIFIED BY 'password' REQUIRE SSL;

接下来,在服务器上授予新用户复制权限:

GRANT REPLICATION SLAVE ON *.* TO 'repl'@'%';

然后刷新权限以实施更改:

FLUSH PRIVILEGES;

之后,重新启用二进制日志记录以恢复正常操作:

SET SQL_LOG_BIN=1;

接下来,设置 group_replication_recovery 通道以使用您的新复制用户及其相关密码。 然后,每个服务器将使用这些凭据对组进行身份验证:

CHANGE REPLICATION SOURCE TO SOURCE_USER='repl', SOURCE_PASSWORD='password' FOR CHANNEL 'group_replication_recovery';

注意:如果您使用的 MySQL 版本早于 8.0.23,则需要使用 MySQL 的旧语法进行设置:

CHANGE MASTER TO MASTER_USER='repl', MASTER_PASSWORD='password' FOR CHANNEL 'group_replication_recovery';

使用复制用户,您可以启用 group_replication 插件以准备初始化组:

INSTALL PLUGIN group_replication SONAME 'group_replication.so';

通过运行以下命令验证插件是否处于活动状态:

SHOW PLUGINS;

group_replication 插件将出现在列表底部,因为它是最近添加的插件:

Output+----------------------------+----------+--------------------+----------------------+---------+
| Name                       | Status   | Type               | Library              | License |
+----------------------------+----------+--------------------+----------------------+---------+
|                            |          |                    |                      |         |
| . . .                      | . . .    | . . .              | . . .                | . . .   |
|                            |          |                    |                      |         |
| group_replication          | ACTIVE   | GROUP REPLICATION  | group_replication.so | GPL     |
+----------------------------+----------+--------------------+----------------------+---------+
45 rows in set (0.00 sec)

此输出确认插件已加载并且当前处于活动状态。 在继续下一步之前,确保您已在每个 MySQL 实例上运行本节中的每个命令。

第 5 步 — 启动组复制

现在每个 MySQL 服务器都配置了复制用户并启用了组复制插件,您可以开始启动您的组。

引导第一个节点

要启动组,请在组 的单个成员上 完成以下步骤。 出于演示目的,本指南将在 member1 上完成这些步骤

组成员在最初加入组时依靠现有成员发送复制数据、最新成员列表和其他信息。 因此,您需要使用稍微不同的过程来启动初始组成员,以便它知道不要从其种子列表中的其他成员那里获得此信息。

如果设置,group_replication_bootstrap_group 变量告诉成员它不应该期望从对等点接收信息,而是应该建立一个新组并选举自己为主要成员。 您可以使用以下命令打开此变量:

SET GLOBAL group_replication_bootstrap_group=ON;

然后您可以为初始组成员开始复制:

START GROUP_REPLICATION;

之后,您可以将 group_replication_bootstrap_group 变量设置回 OFF,因为唯一合适的情况是没有现有组成员时:

SET GLOBAL group_replication_bootstrap_group=OFF;

该组将以此服务器作为唯一成员启动。 通过检查 performance_schema 数据库中 replication_group_members 表中的条目来验证这一点:

SELECT * FROM performance_schema.replication_group_members;

此查询将返回代表当前主机的单行:

Output+---------------------------+--------------------------------------+---------------+-------------+--------------+-------------+----------------+----------------------------+
| CHANNEL_NAME              | MEMBER_ID                            | MEMBER_HOST   | MEMBER_PORT | MEMBER_STATE | MEMBER_ROLE | MEMBER_VERSION | MEMBER_COMMUNICATION_STACK |
+---------------------------+--------------------------------------+---------------+-------------+--------------+-------------+----------------+----------------------------+
| group_replication_applier | 13324ab7-1b01-11e7-9dd1-22b78adaa992 | 203.0.113.1  |        3306 | ONLINE       | PRIMARY     | 8.0.28         | XCom                       |
+---------------------------+--------------------------------------+---------------+-------------+--------------+-------------+----------------+----------------------------+
1 row in set (0.00 sec)

MEMBER_STATEONLINE 值表示该节点在组内完全可操作。

接下来使用一些示例数据创建一个测试数据库和表。 将更多成员添加到此组后,此数据将自动复制给他们。

首先创建一个名为 playground 的示例数据库:

CREATE DATABASE playground;

接下来使用以下命令在 playground 数据库中创建一个名为 equipment 的示例表:

CREATE TABLE playground.equipment ( 
id INT NOT NULL AUTO_INCREMENT,
type VARCHAR(50),
quant INT,
color VARCHAR(25),
PRIMARY KEY(id)
);

此表包含以下四列:

  • id:此列将包含自动递增的整数值,这意味着当您使用示例数据加载表时,您不必为此列指定值
  • type:此列将包含字符串值,描述该行代表的游乐场设备类型
  • quant:此列将包含整数值来表示给定类型的游乐场设备的数量
  • color:此列将保存指定给定设备颜色的字符串值

另外,请注意 id 列被指定为该表的主键。 在 MySQL 中,复制到组的每个表都必须有一个指定为表的主键的列。

最后,运行以下命令将一行数据插入表中:

INSERT INTO playground.equipment (type, quant, color) VALUES ("slide", 2, "blue");

查询表以确保数据输入正确:

SELECT * FROM playground.equipment;
Output+----+-------+-------+-------+
| id | type  | quant | color |
+----+-------+-------+-------+
|  1 | slide |     2 | blue  |
+----+-------+-------+-------+
1 row in set (0.00 sec)

在验证此服务器是该组的成员并且它具有写入能力后,其他服务器可以加入该组。

启动剩余节点

接下来,在 member2 上启动组复制。 由于您已经有一个活跃的成员,您不需要引导该组,该成员可以直接加入:

START GROUP_REPLICATION;

member3 上,以相同的方式启动组复制:

START GROUP_REPLICATION;

在三台服务器中的任何一台上再次检查成员列表。 这一次,输出中将列出三台服务器:

SELECT * FROM performance_schema.replication_group_members;
Output
+---------------------------+--------------------------------------+---------------+-------------+--------------+-------------+----------------+----------------------------+
| CHANNEL_NAME              | MEMBER_ID                            | MEMBER_HOST   | MEMBER_PORT | MEMBER_STATE | MEMBER_ROLE | MEMBER_VERSION | MEMBER_COMMUNICATION_STACK |
+---------------------------+--------------------------------------+---------------+-------------+--------------+-------------+----------------+----------------------------+
| group_replication_applier | 13324ab7-1b01-11e7-9dd1-22b78adaa992 | 203.0.113.1  |        3306 | ONLINE       | PRIMARY     | 8.0.28         | XCom                       |
| group_replication_applier | 1ae4b211-1b01-11e7-9d89-ceb93e1d5494 | 203.0.113.2  |        3306 | ONLINE       | SECONDARY   | 8.0.28         | XCom                       |
| group_replication_applier | 157b597a-1b01-11e7-9d83-566a6de6dfef | 203.0.113.3  |        3306 | ONLINE       | SECONDARY   | 8.0.28         | XCom                       |
+---------------------------+--------------------------------------+---------------+-------------+--------------+-------------+----------------+----------------------------+
3 rows in set (0.00 sec)

所有成员的 MEMBER_STATE 值都应为 ONLINE。 对于一个新组,如果任何节点被列为 RECOVERING 超过几秒钟,这通常表明发生了错误或配置错误。 检查 /var/log/mysql/error.log 上的日志以获取有关问题的更多信息。

接下来,检查测试数据库信息是否已复制到新成员上:

SELECT * FROM playground.equipment;
Output+----+-------+-------+-------+
| id | type  | quant | color |
+----+-------+-------+-------+
|  1 | slide |     2 | blue  |
+----+-------+-------+-------+
1 row in set (0.01 sec)

如果数据在新成员上可用,则意味着组复制工作正常。

第 6 步 — 测试新组成员的写入能力

接下来,您可以尝试从新的复制组成员写入数据库。 这是否成功取决于您选择配置单个主组还是多主组。

在单一主要环境中测试写入

在单个主组中,出于一致性原因,您应该期望来自非主服务器的任何写入操作都会被拒绝。 通过对复制组的任何成员运行以下查询,您可以随时找到当前的主数据库:

SHOW STATUS LIKE '%primary%';
Output+----------------------------------+--------------------------------------+
| Variable_name                    | Value                                |
+----------------------------------+--------------------------------------+
| group_replication_primary_member | 13324ab7-1b01-11e7-9dd1-22b78adaa992 |
+----------------------------------+--------------------------------------+
1 row in set (0.01 sec)

查询的值将是一个 MEMBER_ID ,您可以像以前一样通过查询组成员列表来匹配主机:

SELECT * FROM performance_schema.replication_group_members;
Output+---------------------------+--------------------------------------+--------------+-------------+--------------+
| CHANNEL_NAME              | MEMBER_ID                            | MEMBER_HOST  | MEMBER_PORT | MEMBER_STATE |
+---------------------------+--------------------------------------+--------------+-------------+--------------+
| group_replication_applier | 13324ab7-1b01-11e7-9dd1-22b78adaa992 | 203.0.113.1  |        3306 | ONLINE       |
| group_replication_applier | 1ae4b211-1b01-11e7-9d89-ceb93e1d5494 | 203.0.113.2  |        3306 | ONLINE       |
| group_replication_applier | 157b597a-1b01-11e7-9d83-566a6de6dfef | 203.0.113.3  |        3306 | ONLINE       |
+---------------------------+--------------------------------------+--------------+-------------+--------------+
3 rows in set (0.01 sec)

正如此示例输出所示,位于 203.0.113.1member1 的主机当前是主服务器。 如果您尝试从其他成员写入数据库,则操作将失败:

INSERT INTO playground.equipment (type, quant, color) VALUES ("swing", 10, "yellow");
OutputERROR 1290 (HY000): The MySQL server is running with the --super-read-only option so it cannot execute this statement

这是意料之中的,因为该组当前配置有一个可写入的主数据库。 如果主服务器有问题离开组,组会自动选举一个新成员作为主服务器并接受写入。

在多主环境中测试写入

对于已配置为多主方向的组,任何成员都应该能够向数据库提交写入。

您可以通过再次检查 group_replication_primary_member 变量的值来仔细检查您的组是否在多主模式下运行:

SHOW STATUS LIKE '%primary%';
Output+----------------------------------+-------+
| Variable_name                    | Value |
+----------------------------------+-------+
| group_replication_primary_member |       |
+----------------------------------+-------+
1 row in set (0.02 sec)

如果变量为空,这意味着没有指定的主主机并且任何成员都应该能够接受写入。

通过尝试将一些数据写入 equipment 表,在 member2 上进行测试:

INSERT INTO playground.equipment (type, quant, color) VALUES ("swing", 10, "yellow");
OutputQuery OK, 1 row affected (0.00 sec)

member2 提交了写操作,没有任何错误。

member3 上,运行以下查询以检查是否添加了新项目:

SELECT * FROM playground.equipment;
Output+----+-------+-------+--------+
| id | type  | quant | color  |
+----+-------+-------+--------+
|  1 | slide |     2 | blue   |
|  2 | swing |    10 | yellow |
+----+-------+-------+--------+
2 rows in set (0.00 sec)

这确认 member2 的写入已成功复制。

现在,通过运行以下 INSERT 语句来测试 member3 上的写入功能:

INSERT INTO playground.equipment (type, quant, color) VALUES ("seesaw", 3, "green");
OutputQuery OK, 1 row affected (0.02 sec)

回到 member1,测试以确保两个新成员的写操作都被复制回来:

SELECT * FROM playground.equipment;
Output+----+--------+-------+--------+
| id | type   | quant | color  |
+----+--------+-------+--------+
|  1 | slide  |     2 | blue   |
|  2 | swing  |    10 | yellow |
|  3 | seesaw |     3 | green  |
+----+--------+-------+--------+
3 rows in set (0.01 sec)

这证实了复制在每个方向上都在工作,并且每个成员都能够执行写操作。

第 7 步 — 恢复组

一旦组被引导,单个成员可以加入和离开而不影响可用性,只要有足够的成员来选举主服务器。 但是,如果进行了某些配置更改(例如在单主环境和多主环境之间切换),或者组的所有成员都离开了,您可能需要以与最初相同的方式重新引导组。

member1 上,将 group_replication_bootstrap_group 变量设置为 ON

SET GLOBAL GROUP_REPLICATION_BOOTSTRAP_GROUP=ON;

然后初始化组:

START GROUP_REPLICATION;

之后,您可以将 group_replication_bootstrap_group 变量设置回 OFF

SET GLOBAL GROUP_REPLICATION_BOOTSTRAP_GROUP=OFF;

一旦第一个成员开始组,其他成员可以加入:

START GROUP_REPLICATION;

对任何其他成员执行此过程:

START GROUP_REPLICATION;

该组现在应该在线,所有成员都可用:

SELECT * FROM performance_schema.replication_group_members;
Output+---------------------------+--------------------------------------+--------------+-------------+--------------+
| CHANNEL_NAME              | MEMBER_ID                            | MEMBER_HOST  | MEMBER_PORT | MEMBER_STATE |
+---------------------------+--------------------------------------+--------------+-------------+--------------+
| group_replication_applier | 13324ab7-1b01-11e7-9dd1-22b78adaa992 | 203.0.113.1  |        3306 | ONLINE       |
| group_replication_applier | 1ae4b211-1b01-11e7-9d89-ceb93e1d5494 | 203.0.113.2  |        3306 | ONLINE       |
| group_replication_applier | 157b597a-1b01-11e7-9d83-566a6de6dfef | 203.0.113.3  |        3306 | ONLINE       |
+---------------------------+--------------------------------------+--------------+-------------+--------------+
3 rows in set (0.01 sec)

此过程可用于在必要时重新启动组。

第 8 步 — MySQL 启动时自动加入组

使用当前设置,如果成员服务器重新启动,它不会在启动时自动重新加入组。 如果您希望成员自动重新加入群组,您可以稍微修改配置文件。

当您希望成员在启动时自动加入时,此步骤中概述的设置很有帮助。 但是,您应该注意一些事项。 首先,此设置仅影响 MySQL 实例本身的启动时间。 如果成员因超时问题从组中删除,但 MySQL 实例仍然在线,则该成员不会自动重新加入。

其次,在首次引导组时启用此设置可能是有害的。 当没有要加入的现有组时,MySQL 进程将需要很长时间才能启动,因为它会尝试联系其他不存在的成员进行初始化。 只有经过长时间的超时,它才会放弃并正常启动。 之后,您将不得不使用上述过程来引导组。

考虑到上述注意事项,如果您希望配置节点在 MySQL 启动时自动加入组,请打开主 MySQL 配置文件:

sudo nano /etc/mysql/my.cnf

在里面,找到 loose-group_replication_start_on_boot 变量,并将其设置为 ON

/etc/mysql/my.cnf

[mysqld]
. . .
loose-group_replication_start_on_boot = ON
. . .

完成后保存并关闭文件。 该成员应在其 MySQL 实例下次启动时自动尝试加入该组。

结论

通过完成本教程,您了解了如何在三个 Ubuntu 20.04 服务器之间配置 MySQL 组复制。 对于单主设置,成员将在必要时自动选择具有写入能力的主。 对于多主组,任何成员都可以执行写入和更新。

组复制提供了灵活的复制拓扑,允许成员随意加入或离开,同时提供数据一致性和消息排序的保证。 MySQL 组复制的配置可能有点复杂,但它提供了传统复制无法提供的功能。