如何在Ubuntu 20.04上配置MySQL组复制

介绍

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

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

在本教程中,您将使用一组三个Ubuntu 20.04服务器设置MySQL组复制。请注意,三个是在MySQL中部署组复制所需的最少MySQL实例数量,而九个是最大数量。在完成本教程时,您将有选择将该组设置为单主或多主复制组的选项。

注意:数据库服务器在复制设置中可以扮演两种角色之一:它们可以是一个主实例(也称为实例),用户可以向其写入数据;或者是一个副本(或次要实例),它存储源上所有数据的副本。从历史上看,这些角色通常被称为主实例从实例。在2020年7月发表的一篇博文中,MySQL团队承认了这种术语的负面含义,并宣布他们正在努力更新数据库程序及其文档,以使用更加包容的语言。

然而,这是一个持续进行的过程。虽然MySQL的文档和该程序第8版的许多命令已经更新,将复制拓扑中的服务器称为主服务器及其次要服务器(或及其副本),但仍然有一些地方出现了负面术语。本指南将尽可能使用更加包容的术语,但在一些情况下,旧术语不可避免地会出现。

先决条件

要完成本指南,您需要:

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

为了保持清晰,本指南将把这三台服务器称为member1member2member3。在本指南的示例中,这些成员将具有以下IP地址:

Member IP address
member1 203.0.113.1
member2 203.0.113.2
member3 203.0.113.3

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

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

而在member3上运行的任何命令将具有绿色背景:

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

步骤 1 — 生成用于识别 MySQL 组的 UUID

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

member1 上,使用 uuidgen 命令生成一个有效的 UUID 用于该组:

  1. uuidgen
Output
168dcb64-7cce-473a-b338-6501f305e561

复制您收到的值,因为在配置服务器池的组名时,您一会儿需要引用这个值。

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

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

  1. 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
. . .
# 通用复制设置
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
. . .
# 共享复制组配置
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服务器上应该相同,请确保仔细复制它。

选择单主或多主

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

如果您希望配置一个多主组,请取消注释loose-group_replication_single_primary_modeloose-group_replication_enforce_update_everywhere_checks指令。这将设置一个多主组。对于单主组,只需将这两行保持注释状态:

/etc/mysql/my.cnf
. . .
# 单主或多主模式?取消注释这两行
# 以启用多主模式,其中任何主机都可以接受写入
#loose-group_replication_single_primary_mode = OFF
#loose-group_replication_enforce_update_everywhere_checks = ON
. . .

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

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

主机特定的配置设置

第四节包含在每台服务器上都不同的设置,包括:

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

server_id 指令必须设置为唯一的数字。对于第一个成员,将其设置为 1,并在每个额外的主机上递增该数字。将 bind-addressreport_host 分别设置为该服务器的 IP 地址,以便 MySQL 实例监听外部连接并正确向其他主机报告其地址。 loose-group_replication_local_address 也应设置为当前服务器的 IP 地址,后面跟着组复制端口(33061)。

举例来说,以下是用于 member1 的配置部分,使用其示例 IP 地址:

/etc/mysql/my.cnf
. . .
# 主机特定的复制配置
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
. . .
# 主机特定的复制配置
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
. . .
# 主机特定的复制配置
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 地址为您正在编辑其配置的服务器的 IP 地址。

完成后,请仔细检查每个主机上的共享复制设置是否相同,并且主机特定设置是否针对每个主机进行了定制。完成后,请保存并关闭每个主机上的文件。如果您使用 nano 编辑文件,则可以通过按 CTRL + XY,然后 ENTER 来完成此操作。

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

  1. sudo systemctl restart mysql

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

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

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

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

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

  1. sudo ufw allow from member2_server_ip to any port 3306
  2. sudo ufw allow from member2_server_ip to any port 33061

确保更改member2_server_ip以反映您的成员2服务器的实际IP地址。然后,要为成员3打开相同的端口,请运行以下命令:

  1. sudo ufw allow from member3_server_ip to any port 3306
  2. sudo ufw allow from member3_server_ip to any port 33061

接下来,更新另外两台服务器的防火墙规则。在成员2上运行以下命令,确保将IP地址更改为成员1成员3的IP地址:

  1. sudo ufw allow from member1_server_ip to any port 3306
  2. sudo ufw allow from member1_server_ip to any port 33061
  3. sudo ufw allow from member3_server_ip to any port 3306
  4. sudo ufw allow from member3_server_ip to any port 33061

最后,在成员3上运行以下两个命令。再次确保您为每台服务器输入了正确的IP地址:

  1. sudo ufw allow from member1_server_ip to any port 3306
  2. sudo ufw allow from member1_server_ip to any port 33061
  3. sudo ufw allow from member2_server_ip to any port 3306
  4. sudo ufw allow from member2_server_ip to any port 33061

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

有了对MySQL端口的访问权限,现在您可以创建一个复制用户并启用组复制插件。

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

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

您的每个MySQL服务器上,使用管理用户登录到MySQL实例,开始交互式会话:

  1. sudo mysql

注意:确保在每个MySQL实例中运行本节中的每个命令

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

  1. SET SQL_LOG_BIN=0;

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

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

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

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

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

  1. FLUSH PRIVILEGES;

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

  1. SET SQL_LOG_BIN=1;

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

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

注意: 如果您使用的是早于8.0.23版本的MySQL,则需要使用MySQL的传统语法来设置此功能:

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

安装好复制用户后,您可以启用group_replication插件以准备初始化组:

  1. INSTALL PLUGIN group_replication SONAME 'group_replication.so';

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

  1. 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变量,则告诉成员不应期望从对等方接收信息,而应建立一个新群组并选举自己为主要成员。您可以使用以下命令打开此变量:

  1. SET GLOBAL group_replication_bootstrap_group=ON;

然后,您可以为初始群组成员启动复制:

  1. START GROUP_REPLICATION;

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

  1. SET GLOBAL group_replication_bootstrap_group=OFF;

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

  1. 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的示例数据库:

  1. CREATE DATABASE playground;

接下来使用以下命令创建名为equipment的示例表,该表位于playground数据库中:

  1. CREATE TABLE playground.equipment (
  2. id INT NOT NULL AUTO_INCREMENT,
  3. type VARCHAR(50),
  4. quant INT,
  5. color VARCHAR(25),
  6. PRIMARY KEY(id)
  7. );

该表包含以下四列:

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

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

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

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

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

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

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

启动其余节点

接下来,在成员2上启动组复制。由于您已经有一个活动成员,因此无需引导组,此成员可以直接加入:

  1. START GROUP_REPLICATION;

成员3上,以相同的方式启动组复制:

  1. START GROUP_REPLICATION;

再次检查任意三个服务器上的成员列表。此时,输出中将列出三个服务器:

  1. 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中的日志,以获取有关出错原因的其他信息。

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

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

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

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

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

在单主环境中测试写入

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

  1. 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,您可以通过像之前一样查询组成员列表来将其与主机匹配:

  1. 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.1的主机 — member1 — 目前是主服务器。如果您尝试从另一个成员向数据库写入,操作将失败:

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

这是预期的,因为该组当前配置为单个可写主。如果主服务器出现问题并离开组,组将自动选举新成员成为主服务器并接受写入。

在多主环境中测试写入

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

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

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

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

成员2上测试,尝试向equipment表写入一些数据:

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

成员2在没有任何错误的情况下提交了写操作。

成员3上运行以下查询,以检查是否已添加新项目:

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

这确认了成员2的写入已成功复制。

现在,通过运行以下INSERT语句,在成员3上测试写入功能:

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

回到成员1,确保来自这两个新成员的写入操作都已复制:

  1. 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 —— 恢复组

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

成员1上,将group_replication_bootstrap_group变量设置为ON

  1. SET GLOBAL GROUP_REPLICATION_BOOTSTRAP_GROUP=ON;

然后初始化组:

  1. START GROUP_REPLICATION;

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

  1. SET GLOBAL GROUP_REPLICATION_BOOTSTRAP_GROUP=OFF;

一旦第一个成员启动了组,其他成员就可以加入:

  1. START GROUP_REPLICATION;

按照这个过程添加任何其他成员:

  1. START GROUP_REPLICATION;

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

  1. 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 配置文件:

  1. 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 组复制可能会更复杂一些,但它提供了传统复制中不可能实现的功能。

Source:
https://www.digitalocean.com/community/tutorials/how-to-configure-mysql-group-replication-on-ubuntu-20-04