mysql集群部署(Mysql Group Replication)

创建容错系统的最常见方法是使组件冗余,换句话说,可以删除组件,系统应继续按预期运行。具体来说,复制数据库必须处理这样一个事实,即它们需要维护和管理多台服务器,而不仅仅是一台。此外,由于服务器正在合作创建组,因此必须处理其他几个经典的分布式系统问题,例如网络分区或裂脑场景。

因此,最终的挑战是将数据库和数据复制的逻辑与以一致且简单的方式协调多个服务器的逻辑相融合。换句话说,让多个服务器就系统状态和系统经历的每一次更改的数据达成一致。这可以概括为让服务器就每个数据库状态转换达成一致,以便它们都作为一个单一的数据库进行,或者它们最终会聚到相同的状态。这意味着它们需要作为(分布式)状态机运行。

MySQL Group Replication 提供分布式状态机复制,服务器之间具有很强的协调性。当服务器属于同一组时,它们会自动进行自我协调。该组可以在具有自动主要选举的单主要模式下运行,其中一次只有一台服务器接受更新。或者,对于更高级的用户,可以在多主模式下部署该组,其中所有服务器都可以接受更新,即使它们是同时发布的。这种能力是以应用程序必须解决此类部署所施加的限制为代价的。

有一个内置的组成员服务,可以使组的视图在任何给定时间点保持一致并可用于所有服务器。服务器可以离开和加入组,视图会相应更新。有时服务器可能会意外离开组,在这种情况下,故障检测机制会检测到这种情况并通知组视图已更改。这都是自动的。

对于要提交的事务,组中的大多数人必须就全局事务序列中给定事务的顺序达成一致。决定提交或中止事务由每个服务器单独完成,但所有服务器都会做出相同的决定。如果存在网络分裂,导致成员无法达成一致的分裂,那么在解决这个问题之前,系统不会进步。因此,还有一个内置的、自动的、裂脑保护机制。

所有这些都由提供的组通信系统 (GCS) 协议提供支持。它们提供故障检测机制、组成员服务以及安全且完全有序的消息传递。所有这些属性都是创建系统的关键,该系统可确保跨服务器组一致地复制数据。这项技术的核心是 Paxos 算法的实现。它充当群组通信引擎。

为组复制部署实例(参见 myql 安装,三个文件夹)

第一步是部署至少三个 MySQL 服务器实例,此过程演示了为实例使用多个主机,名称为 s1、s2 和 s3。假设每台主机上都安装了 MySQL 服务器,Group Replication是MySQL Server 8.0自带的MySQL插件,不需要额外安装。

在这个例子中,三个实例用于组,这是创建组的最小实例数。添加更多实例可提高组的容错能力。例如,如果该组由三个成员组成,则在一个实例失败的情况下该组可以继续。但如果发生另一次故障,该组将无法再继续处理写入事务。通过添加更多实例,在组继续处理事务时可能发生故障的服务器数量也会增加。一个组中可以使用的最大实例数为九个

配置组复制实例

存储引擎

对于组复制,数据必须存储在 InnoDB 事务存储引擎中(有关原因的详细信息,使用其他存储引擎,包括临时 MEMORY存储引擎,可能会导致组复制错误。如下设置 disabled_storage_engines 系统变量以防止使用它们

sql 复制代码
disabled_storage_engines="MyISAM,BLACKHOLE,FEDERATED,ARCHIVE,MEMORY"

复制框架

以下设置根据 MySQL 组复制要求配置复制。

这些设置将服务器配置为使用唯一标识符号 1,以启用"使用全局事务标识符进行复制",并只允许执行可以使用 GTID 安全记录的语句。

sql 复制代码
#将服务器配置为使用唯一标识符号1,注意的是同组中不能重复
server_id=1
gtid_mode=ON
enforce_gtid_consistency=ON
#此设置禁用写入二进制日志的事件的校验和,默认为启用。
#从 MySQL 8.0.21 开始,Group Replication 支持在二进制日志中存在校验和,并且可以使用它们来验证某些通道上事件的完整性,因此您可以使用默认设置
binlog_checksum=NONE

组复制设置

sql 复制代码
#linux使用的是group_replication.so,windows中使用的是group_replication.dll
plugin_load_add='group_replication.dll'
#替换成真实的uuid
group_replication_group_name="aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa"
group_replication_start_on_boot=off
#将s1替换成真实的主机地址,也就是你mysql的安装地址,其中的33061是组内成员通信的端口,区别于
group_replication_local_address= "s1:33061"
#下面是组内的其他成员地址
group_replication_group_seeds= "s1:33061,s2:33061,s3:33061"
group_replication_bootstrap_group=off
  • <font style="color:rgb(0, 0, 0);">plugin-load-add</font>将 Group Replication 插件添加到服务器在启动时加载的插件列表中。这在生产部署中比手动安装插件更可取。
  • 配置 group_replication_group_name 告诉插件它正在加入或创建的组名为"aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa"。的值 group_replication_group_name 必须是有效的 UUID。你可以<font style="color:rgb(0, 0, 0);">SELECT UUID()</font>用来生成一个。此 UUID 构成 GTID 的一部分,当组成员从客户端接收到的事务以及组成员内部生成的视图更改事件被写入二进制日志时使用。
  • 配置 group_replication_start_on_boot 变量以<font style="color:rgb(0, 0, 0);">off</font>指示插件在服务器启动时不自动启动操作。这在设置组复制时很重要,因为它确保您可以在手动启动插件之前配置服务器。配置成员后,您可以设置 group_replication_start_on_boot<font style="color:rgb(0, 0, 0);">on</font>在服务器启动时自动启动组复制。
  • 配置 group_replication_local_address 设置成员用于与组中其他成员进行内部通信的网络地址和端口。Group Replication 使用此地址进行涉及组通信引擎远程实例(XCom,一种 Paxos 变体)的内部成员到成员连接。

分布式恢复的用户凭证

组复制使用分布式恢复过程在组成员加入组时同步组成员。分布式恢复涉及使用名为的复制通道将事务从捐赠者的二进制日志传输到加入成员<font style="color:rgb(0, 0, 0);">group_replication_recovery</font>. 因此,您必须设置具有正确权限的复制用户,以便 Group Replication 可以建立直接的成员到成员复制通道。如果已将组成员设置为支持使用远程克隆操作作为分布式恢复的一部分(从 MySQL 8.0.17 开始可用),则此复制用户也用作供体上的克隆用户,并且需要正确的权限也为了这个角色。

相同的复制用户必须用于每个组成员的分布式恢复。分布式恢复创建复制用户的过程可以在二进制日志中捕获,然后可以依赖分布式恢复来复制创建用户的语句。或者,您可以在创建复制用户之前禁用二进制日志记录,然后在每个成员上手动创建用户,例如,如果您希望避免将更改传播到其他服务器实例。如果这样做,请确保在配置用户后重新启用二进制日志记录。

  1. 启动 Mysql 服务器实例,然后连接上
  2. 如果要禁用二进制日志记录一遍在每个实力上单独创建复制用户,请通过发出以下语句来实现
sql 复制代码
mysql> SET SQL_LOG_BIN=0;
  1. 创建具有以下权限的 mysql 用户
sql 复制代码
#rpl_user是用户名,可以自行定义,定义后记得下面的语句同样更换,password为要设置的密码,可以自行定义
mysql> CREATE USER rpl_user@'%' IDENTIFIED BY 'password';
#这是与捐赠者建立分布式恢复连接以检索数据所必需的。
mysql> GRANT REPLICATION SLAVE ON *.* TO rpl_user@'%';
#如果涉及的服务器之一处于脱机模式,则可确保组复制连接不会终止。
mysql> GRANT CONNECTION_ADMIN ON *.* TO rpl_user@'%';
#如果复制组中的服务器设置为支持克隆成员需要此特权才能在分布式恢复的克隆操作中充当捐助者
mysql> GRANT BACKUP_ADMIN ON *.* TO rpl_user@'%';
#如果 MySQL 通信堆栈正在用于复制组,用户帐户需要此权限才能使用 MySQL 通信堆栈为组复制建立和维护连接。
mysql> GRANT GROUP_REPLICATION_STREAM ON *.* TO rpl_user@'%';
mysql> FLUSH PRIVILEGES;
  1. 如果刚刚禁用了二进制日志记录,需要在创建用吼吼立即通过发出以下语句再次启用它
sql 复制代码
SET SQL_LOG_BIN=1;
  1. 创建复制用户后,必须向服务器提供用户凭据以用于分布式恢复
sql 复制代码
mysql> CHANGE MASTER TO MASTER_USER='rpl_user', MASTER_PASSWORD='password'  FOR CHANNEL 'group_replication_recovery';

启动组复制

由于我们上面已经配置了plugin_load_add='group_replication.dll',所以现在只需要执行 SHOW PLUGINS;查询插件是否已经安装上了,如果有 group_replication 即可,如果没有则执行下面的语句来安装

sql 复制代码
INSTALL PLUGIN group_replication SONAME 'group_replication.dll'

引导组

第一次启动组的过程称为引导。您使用 group_replication_bootstrap_group 系统变量来引导一个组。引导程序只能由一台服务器完成,即启动组的服务器,并且只能启动一次。这就是 group_replication_bootstrap_group 选项的值未存储在实例的选项文件中的原因。如果它保存在选项文件中,则在重新启动服务器时会自动引导第二个同名的组。这将导致两个不同的组具有相同的名称。相同的推理适用于将此选项设置为 来停止和重新启动插件<font style="color:rgb(0, 0, 0);">ON</font>。因此,为了安全地引导组,连接到 s1 并发出以下语句:

sql 复制代码
#先开启
mysql> SET GLOBAL group_replication_bootstrap_group=ON;
#设置复制的用户凭据
mysql> START GROUP_REPLICATION USER='rpl_user', PASSWORD='password';
#马上关闭
mysql> SET GLOBAL group_replication_bootstrap_group=OFF;

语句返回后,该START GROUP_REPLICATION 组已启动。您可以检查该组现在是否已创建并且其中是否有一名成员:

sql 复制代码
mysql> SELECT * FROM performance_schema.replication_group_members;
+---------------------------+--------------------------------------+-------------+-------------+---------------+-------------+----------------+----------------------------+
| CHANNEL_NAME              | MEMBER_ID                            | MEMBER_HOST | MEMBER_PORT | MEMBER_STATE  | MEMBER_ROLE | MEMBER_VERSION | MEMBER_COMMUNICATION_STACK |
+---------------------------+--------------------------------------+-------------+-------------+---------------+-------------+----------------+----------------------------+
| group_replication_applier | ce9be252-2b71-11e6-b8f4-00212844f856 |   s1        |       3306  | ONLINE        |             |                | XCom                       |
+---------------------------+--------------------------------------+-------------+-------------+---------------+-------------+----------------+----------------------------+
1 row in set (0.0108 sec)

为了证明服务器确实在一个组中并且能够处理负载,创建一个表并向其中添加一些内容。

sql 复制代码
mysql> CREATE DATABASE test;
mysql> USE test;
mysql> CREATE TABLE t1 (c1 INT PRIMARY KEY, c2 TEXT NOT NULL);
mysql> INSERT INTO t1 VALUES (1, 'Luis');

检查表的内容<font style="color:rgb(0, 0, 0);">t1</font>和二进制日志。

sql 复制代码
mysql> SELECT * FROM t1;
+----+------+
| c1 | c2   |
+----+------+
|  1 | Luis |
+----+------+

mysql> SHOW BINLOG EVENTS;
+---------------+-----+----------------+-----------+-------------+--------------------------------------------------------------------+
| Log_name      | Pos | Event_type     | Server_id | End_log_pos | Info                                                               |
+---------------+-----+----------------+-----------+-------------+--------------------------------------------------------------------+
| binlog.000001 |   4 | Format_desc    |         1 |         123 | Server ver: 8.0.31-log, Binlog ver: 4                              |
| binlog.000001 | 123 | Previous_gtids |         1 |         150 |                                                                    |
| binlog.000001 | 150 | Gtid           |         1 |         211 | SET @@SESSION.GTID_NEXT= 'aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa:1'  |
| binlog.000001 | 211 | Query          |         1 |         270 | BEGIN                                                              |
| binlog.000001 | 270 | View_change    |         1 |         369 | view_id=14724817264259180:1                                        |
| binlog.000001 | 369 | Query          |         1 |         434 | COMMIT                                                             |
| binlog.000001 | 434 | Gtid           |         1 |         495 | SET @@SESSION.GTID_NEXT= 'aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa:2'  |
| binlog.000001 | 495 | Query          |         1 |         585 | CREATE DATABASE test                                               |
| binlog.000001 | 585 | Gtid           |         1 |         646 | SET @@SESSION.GTID_NEXT= 'aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa:3'  |
| binlog.000001 | 646 | Query          |         1 |         770 | use `test`; CREATE TABLE t1 (c1 INT PRIMARY KEY, c2 TEXT NOT NULL) |
| binlog.000001 | 770 | Gtid           |         1 |         831 | SET @@SESSION.GTID_NEXT= 'aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa:4'  |
| binlog.000001 | 831 | Query          |         1 |         899 | BEGIN                                                              |
| binlog.000001 | 899 | Table_map      |         1 |         942 | table_id: 108 (test.t1)                                            |
| binlog.000001 | 942 | Write_rows     |         1 |         984 | table_id: 108 flags: STMT_END_F                                    |
| binlog.000001 | 984 | Xid            |         1 |        1011 | COMMIT /* xid=38 */                                                |
+---------------+-----+----------------+-----------+-------------+--------------------------------------------------------------------+

如上所示,创建了数据库和表对象,并将它们对应的 DDL 语句写入二进制日志。此外,数据被插入到表中并写入二进制日志,因此它可以用于从捐赠者的二进制日志通过状态传输进行分布式恢复。

向组中添加实例

现在组中已经有一个实例,s1 ,下面我们开始添加第二个实例

其他实例和第一个实例不同的配置就是 server_id 和group_replication_local_address,所以自行设置即可

如果在 s1 上配置用户凭证时没有启用二进制日志记录,并且没有使用远程克隆操作进行状态传输,则必须在 s2 上创建复制用户。在这种情况下,连接到 s2 并发出:

sql 复制代码
SET SQL_LOG_BIN=0;
CREATE USER rpl_user@'%' IDENTIFIED BY 'password';
GRANT REPLICATION SLAVE ON *.* TO rpl_user@'%';
GRANT CONNECTION_ADMIN ON *.* TO rpl_user@'%';
GRANT BACKUP_ADMIN ON *.* TO rpl_user@'%';
GRANT GROUP_REPLICATION_STREAM ON *.* TO rpl_user@'%';
FLUSH PRIVILEGES;
SET SQL_LOG_BIN=1;

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

START GROUP_REPLICATION USER='rpl_user', PASSWORD='password';

SELECT * FROM performance_schema.replication_group_members;

本地部署组复制

只需要在配置中添加report_host=127.0.0.1即可

:::info

  1. 如果 net start mysql 无法启动,则可以使用 mysql --console 来查看日志信息,根据日志信息对应的进行解决
  2. 如果开启组复制后状态一直没有变成 onlion,则去 data 文件夹下查找 err 后缀的文件,是 mysql 的执行日志
    1. The server is not configured properly to be an active member of the group. Please see more details on error log.,证明配置组复制设置时有问题,server_id 是否唯一,后面的组成员地址是否设置成功等
    2. Plugin group_replication reported: 'There was an error when connecting to the donor server. Please check that group_replication_recovery channel credentials and all MEMBER_HOST column values of performance_schema.replication_group_members table are correct and DNS resolvable.',凭证错误,是否设置了组复制的凭证信息
    3. Replica I/O for channel 'group_replication_recovery': Fatal error: Invalid (empty) username when attempting to connect to the source server. Connection attempt terminated. Error_code: MY-013117 用户名无效或为空,需要设置组复制的用户名
    4. Replica I/O for channel 'group_replication_recovery': Error connecting to source 'rpl_user@127.0.0.1:3310'. This was attempt 1/1, with a delay of 60 seconds between attempts. Message: Authentication plugin 'caching_sha2_password' reported error: Authentication requires secure connection. Error_code: MY-002061,这个错误表明在组复制恢复过程中,连接到源服务器时出现了认证问题。可以尝试修改认证方式,修改前一定要关闭二进制日志
      • 可以将用户的认证方式修改为mysql_native_password,这种认证方式不需要安全连接。
      • 以管理员身份登录到 MySQL,执行以下语句修改用户的认证方式:
      • ALTER USER 'rpl_user'@'%' IDENTIFIED WITH mysql_native_password BY 'password';
      • 将上述语句中的rpl_userpassword替换为实际的用户名和密码。

:::

查询是否有对应的用户信息

sql 复制代码
SELECT user, host FROM mysql.user WHERE user='rpl_user' AND host='%';
相关推荐
c#上位机7 小时前
wpf中资源的使用
c#·wpf
周小码7 小时前
pgroll:简化PostgreSQL零停机迁移
数据库·postgresql
代码的余温7 小时前
解析SQL Server核心服务与功能
数据库·sqlserver
没刮胡子7 小时前
mysql分页SQL
数据库·sql·mysql
fatsheep洋7 小时前
sql项目总结
数据库·sql
高级测试工程师欧阳7 小时前
SQLint3 模块如何使用
数据库·python·mysql·oracle
ActionTech7 小时前
2025 年 8 月《大模型 SQL 能力排行榜》发布
数据库·sql·oracle
小池先生7 小时前
docker中的mysql变更宿主机映射端口
android·mysql·docker
一心0927 小时前
SQL(window)日志在linux 下查看
linux·数据库·windows·sql·日志