mysql8.0使用MGR实现高可用

时间:2024-03-04 14:47:53

一、三节点MGR集群的安装部署

1. 安装准备

准备好下面三台服务器:  

IP 端口 角色
192.168.150.21 3306 mgr1
192.168.150.22 3306 mgr2
192.168.150.23 3306 mgr3

配置hosts解析

# cat >> /etc/hosts << EOF
192.168.150.21 mgr1
192.168.150.22 mgr2
192.168.150.23 mgr3
EOF

2. 启动MySQL Server

首先修改 /etc/my.cnf.d/mysql-server.cnf 配置文件,增加:

#/etc/my.cnf*.d/mysql-server.cnf
[mysqld]
...
#开启GTID,必须开启
gtid_mode = ON
#强制GTID的一致性
enforce_gtid_consistency = ON
#binlog格式,MGR要求必须是ROW,不过就算不是MGR,也最好用
binlog_format = row
#server-id必须是唯一的
server-id = 1
#MGR使用乐观锁,所以官网建议隔离级别是RC,减少锁粒度
transaction_isolation = READ-COMMITTED
#因为集群会在故障恢复时互相检查binlog的数据,
#所以需要记录下集群内其他服务器发过来已经执行过的binlog,按GTID来区分是否执行过.
log-slave-updates = 1
#binlog校验规则,5.6之后的高版本是CRC32,低版本都是NONE,但是MGR要求使用NONE
binlog_checksum = NONE
#基于安全的考虑,MGR集群要求复制模式要改成slave记录记录到表中,不然就报错
master_info_repository = TABLE
#同上配套
relay_log_info_repository = TABLE
#组复制设置#记录事务的算法,官网建议设置该参数使用 XXHASH64 算法
transaction_write_set_extraction = XXHASH64
#相当于此GROUP的名字,是UUID值,不能和集群内其他GTID值的UUID混用,可用uuidgen来生成一个新的,
#主要是用来区分整个内网里边的各个不同的GROUP,而且也是这个group内的GTID值的UUID
loose-group_replication_group_name = '5dbabbe6-8050-49a0-9131-1de449167446'
#IP地址白名单,默认只添加127.0.0.1,不会允许来自外部主机的连接,按需安全设置
loose-group_replication_ip_whitelist = '127.0.0.1/8,192.168.0.0/16'
#是否随服务器启动而自动启动组复制,不建议直接启动,怕故障恢复时有扰乱数据准确性的特殊情况
loose-group_replication_start_on_boot = OFF
#本地MGR的IP地址和端口,host:port,是MGR的端口,不是数据库的端口
loose-group_replication_local_address = '192.168.150.21:33081'
#需要接受本MGR实例控制的服务器IP地址和端口,是MGR的端口,不是数据库的端口
loose-group_replication_group_seeds = '192.168.150.21:33081,192.168.150.22:33081,192.168.150.23:33081'
#开启引导模式,添加组成员,用于第一次搭建MGR或重建MGR的时候使用,只需要在集群内的其中一台开启,
loose-group_replication_bootstrap_group = OFF
#是否启动单主模式,如果启动,则本实例是主库,提供读写,其他实例仅提供读,如果为off就是多主模式了
loose-group_replication_single_primary_mode = ON
#多主模式下,强制检查每一个实例是否允许该操作,如果不是多主,可以关闭
loose-group_replication_enforce_update_everywhere_checks = on

 将mgr1的文件发送到mgr2和mgr3, 修改server-id和loose-group_replication_local_address的相关值

# scp /etc/my.cnf.d/mysql-server.cnf mgr2:/etc/my.cnf.d/
# scp /etc/my.cnf.d/mysql-server.cnf mgr2:/etc/my.cnf.d/

3.安装插件(三台机器都要安装)

利用这份配置文件,重启MySQL Server,之后就应该能看到已经成功加载 group_replicaiton 插件了:

[root@mgr1 ~]# mysql -e "show plugins;" | grep "group_replication"

如果没正确加载,也可以登入MySQL Server自行手动加载这个plugin:

[root@mgr1 ~]# mysql -e "install plugin group_replication soname 'group_replication.so'"
[root@mgr1 ~]# mysql -e "show plugins;" | grep "group_replication"
group_replication       ACTIVE  GROUP REPLICATION       group_replication.so    GPL

4.配置账号(三台机器都要配置)

接下来,创建MGR服务专用账户,并准备配置MGR服务通道:

#每个节点都要单独创建用户,因此这个操作没必要记录binlog并复制到其他节点
mysql> set session sql_log_bin=0;
mysql> create user repl@'%' identified with mysql_native_password by 'repl';
mysql> GRANT BACKUP_ADMIN, REPLICATION SLAVE ON *.* TO `repl`@`%`;
#创建完用户后继续启用binlog记录
mysql> set session sql_log_bin=1;

#配置MGR服务通道
#通道名字 group_replication_recovery 是固定的,不能修改
mysql> CHANGE MASTER TO MASTER_USER='repl', MASTER_PASSWORD='repl' FOR CHANNEL 'group_replication_recovery';

5.启动MGR单主模式

在mgr1节点,启动引导,进入mysql服务端

mysql> SET GLOBAL group_replication_bootstrap_group = ON;
mysql> START GROUP_REPLICATION;
mysql> SET GLOBAL group_replication_bootstrap_group = OFF;
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 | 3460f111-9314-11ee-a532-000c295df6cf | mgr1        |        3306 | ONLINE       | PRIMARY     | 8.0.30         | XCom                       |
+---------------------------+--------------------------------------+-------------+-------------+--------------+-------------+----------------+----------------------------+
1 row in set (0.01 sec)

 在mgr2\mgr3节点,进入mysql服务端

mysql> START GROUP_REPLICATION;
mysql> SELECT * FROM performance_schema.replication_group_members;

再次查看MGR节点状态:

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 | 3460f111-9314-11ee-a532-000c295df6cf | mgr1        |        3306 | ONLINE       | PRIMARY     | 8.0.30         | XCom                       |
| group_replication_applier | 52854f96-9314-11ee-8821-000c29ced34f | mgr2        |        3306 | ONLINE       | SECONDARY   | 8.0.30         | XCom                       |
| group_replication_applier | 70fa199f-9314-11ee-a8eb-000c29f957d2 | mgr3        |        3306 | ONLINE       | SECONDARY   | 8.0.30         | XCom                       |
+---------------------------+--------------------------------------+-------------+-------------+--------------+-------------+----------------+----------------------------+
3 rows in set (0.00 sec)

 看到上面这个集群共有3个节点处于ONLINE状态,其中 192.168.150.21PRIMARY 节点,其余两个都是 SECONDARY 节点,也就是说当前这个集群采用 单主 模式。如果采用多主模式,则所有节点的角色都是 PRIMARY

6. 向MGR集群中写入数据

接下来我们连接到 PRIMARY 节点,创建测试库表并写入数据:

mysql> create database mgr;
mysql> use mgr;
mysql> create table t1(c1 int unsigned not null primary key);
mysql> insert into t1 select rand()*10240;
mysql> select * from t1;
+------+
| c1   |
+------+
| 442 |
+------+

 再连接到其中一个 SECONDARY 节点,查看刚刚在 PRIMARY 写入的数据是否可以看到:

mysql> select @@hostname;
+------------+
| @@hostname |
+------------+
| mgr2       |
+------------+
1 row in set (0.00 sec)

mysql> select * from mgr.t1;
+-----+
| c1  |
+-----+
| 442 |
+-----+
1 row in set (0.01 sec)

确认可以读取到该数据。

到这里,就完成了三节点MGR集群的安装部署

二、 MGR管理维护

现在有个三节点的MGR集群:

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 | 3460f111-9314-11ee-a532-000c295df6cf | mgr1        |        3306 | ONLINE       | PRIMARY     | 8.0.30         | XCom                       |
| group_replication_applier | 52854f96-9314-11ee-8821-000c29ced34f | mgr2        |        3306 | ONLINE       | SECONDARY   | 8.0.30         | XCom                       |
| group_replication_applier | 70fa199f-9314-11ee-a8eb-000c29f957d2 | mgr3        |        3306 | ONLINE       | SECONDARY   | 8.0.30         | XCom                       |
+---------------------------+--------------------------------------+-------------+-------------+--------------+-------------+----------------+----------------------------+
3 rows in set (0.00 sec)

1. 切换主节点

当主节点需要进行维护时,或者执行滚动升级时,就可以对其进行切换,将主节点切换到其他节点。

在命令行模式下,可以使用 group_replication_set_as_primary() 这个udf实现切换,例如:

-- 将Primary角色切换到第二个节点
在mgr1上做

mysql> select group_replication_set_as_primary('52854f96-9314-11ee-8821-000c29ced34f');
+--------------------------------------------------------------------------+
| group_replication_set_as_primary('52854f96-9314-11ee-8821-000c29ced34f') |
+--------------------------------------------------------------------------+
| Primary server switched to: 52854f96-9314-11ee-8821-000c29ced34f         |
+--------------------------------------------------------------------------+
1 row in set (0.02 sec)

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 | 3460f111-9314-11ee-a532-000c295df6cf | mgr1        |        3306 | ONLINE       | SECONDARY   | 8.0.30         | XCom                       |
| group_replication_applier | 52854f96-9314-11ee-8821-000c29ced34f | mgr2        |        3306 | ONLINE       | PRIMARY     | 8.0.30         | XCom                       |
| group_replication_applier | 70fa199f-9314-11ee-a8eb-000c29f957d2 | mgr3        |        3306 | ONLINE       | SECONDARY   | 8.0.30         | XCom                       |
+---------------------------+--------------------------------------+-------------+-------------+--------------+-------------+----------------+----------------------------+
3 rows in set (0.00 sec)

顺便提一下,在MySQL 5.7版本中,只能通过重启以实现主节点的自动切换,不能手动切换。从这个角度来说,如果想要使用MGR,最好是选择MySQL 8.0版本,而不要使用5.7版本。

2. 切换单主/多主模式

在命令行模式下,可以调用 group_replication_switch_to_single_primary_mode()group_replication_switch_to_multi_primary_mode() 来切换单主/多主模式。

#直接调用函数即可
mysql> select group_replication_switch_to_multi_primary_mode();
+--------------------------------------------------+
| group_replication_switch_to_multi_primary_mode() |
+--------------------------------------------------+
| Mode switched to multi-primary successfully.     |
+--------------------------------------------------+
1 row in set (1.01 sec)


#查看各节点状态
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 | 3460f111-9314-11ee-a532-000c295df6cf | mgr1        |        3306 | ONLINE       | PRIMARY     | 8.0.30         | XCom                       |
| group_replication_applier | 52854f96-9314-11ee-8821-000c29ced34f | mgr2        |        3306 | ONLINE       | PRIMARY     | 8.0.30         | XCom                       |
| group_replication_applier | 70fa199f-9314-11ee-a8eb-000c29f957d2 | mgr3        |        3306 | ONLINE       | PRIMARY     | 8.0.30         | XCom                       |
+---------------------------+--------------------------------------+-------------+-------------+--------------+-------------+----------------+----------------------------+
3 rows in set (0.00 sec)


#切换成单主模式时可以指定某个节点的 server_uuid,如果不指定则会根据规则自动选择一个新的主节点
#在这里,我选择了指定mgr3节点作为新主
mysql> select group_replication_switch_to_single_primary_mode('70fa199f-9314-11ee-a8eb-000c29f957d2');
+-----------------------------------------------------------------------------------------+
| group_replication_switch_to_single_primary_mode('70fa199f-9314-11ee-a8eb-000c29f957d2') |
+-----------------------------------------------------------------------------------------+
| Mode switched to single-primary successfully.                                           |
+-----------------------------------------------------------------------------------------+
1 row in set (0.02 sec)

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 | 3460f111-9314-11ee-a532-000c295df6cf | mgr1        |        3306 | ONLINE       | SECONDARY   | 8.0.30         | XCom                       |
| group_replication_applier | 52854f96-9314-11ee-8821-000c29ced34f | mgr2        |        3306 | ONLINE       | SECONDARY   | 8.0.30         | XCom                       |
| group_replication_applier | 70fa199f-9314-11ee-a8eb-000c29f957d2 | mgr3        |        3306 | ONLINE       | PRIMARY     | 8.0.30         | XCom                       |
+---------------------------+--------------------------------------+-------------+-------------+--------------+-------------+----------------+----------------------------+
3 rows in set (0.00 sec)

3. 添加新节点

接下来我们演示如何向MGR集群中添加一个新节点。

首先,要先完成MySQL Server初始化,创建好MGR专用账户、设置好MGR服务通道等前置工作。

接下来,直接执行命令 start group_replication 启动MGR服务即可,新增的节点会进入分布式恢复这个步骤,它会从已有节点中自动选择一个作为捐献者(donor),并自行决定是直接读取binlog进行恢复,还是利用Clone进行全量恢复。

如果是已经在线运行一段时间的MGR集群,有一定存量数据,这时候新节点加入可能会比较慢,建议手动利用Clone进行一次全量复制。还记得前面创建MGR专用账户时,给加上了 BACKUP_ADMIN 授权吗,这时候就派上用场了,Clone需要用到这个权限。

下面演示如何利用Clone进行一次全量数据恢复,假定要新增的节点是 192.168.150.24 (给它命名为 mgr4)。

#在mgr4上设置捐献者
#为了降低对Primary节点的影响,建议选择其他Secondary节点
mysql> set global clone_valid_donor_list='192.168.150.24:3306';

#停掉mgr服务(如果有的话),关闭super_read_only模式,然后开始复制数据
#注意这里要填写的端口是3306(MySQL正常服务端口),而不是33061这个MGR服务专用端口
mysql> stop group_replication; set global super_read_only=0; clone INSTANCE FROM repl@192.168.150.21:3306 IDENTIFIED BY 'repl';

全量复制完数据后,该节点会进行一次自动重启。重启完毕后,再次确认 group_replication_group_namegroup_replication_local_addressgroup_replication_group_seeds 这些选项值是否正确,如果没问题,执行 start group_replication 后,该节点应该就可以正常加入集群了。

4. 删除节点

在命令行模式下,一个节点想退出MGR集群,直接执行 stop group_replication 即可,如果这个节点只是临时退出集群,后面还想加回集群,则执行 start group_replication 即可自动再加入。而如果是想彻底退出集群,则停止MGR服务后,执行 reset master; reset slave all; 重置所有复制(包含MGR)相关的信息就可以了。

5. 异常退出的节点重新加回

当节点因为网络断开、实例crash等异常情况与MGR集群断开连接后,这个节点的状态会变成 UNREACHABLE,待到超过 group_replication_member_expel_timeout + 5 秒后,集群会踢掉该节点。等到这个节点再次启动并执行 start group_replication,正常情况下,该节点应能自动重新加回集群。

6. 重启MGR集群

正常情况下,MGR集群中的Primary节点退出时,剩下的节点会自动选出新的Primary节点。当最后一个节点也退出时,相当于整个MGR集群都关闭了。这时候任何一个节点启动MGR服务后,都不会自动成为Primary节点,需要在启动MGR服务前,先设置 group_replication_bootstrap_group=ON,使其成为引导节点,再启动MGR服务,它才会成为Primary节点,后续启动的其他节点也才能正常加入集群。可自行测试,这里不再做演示。

P.S,第一个节点启动完毕后,记得重置选项 group_replication_bootstrap_group=OFF,避免在后续的操作中导致MGR集群分裂。

三、 MGR状态监控

MGR和传统主从复制类似,在运行过程中主要关注各节点的运行状态,以及Secondary节点的事务是否有延迟。本文介绍如何监控MGR节点状态、事务状态等。

1. 节点状态监控

通过查询 performance_schema.replication_group_members 表即可知道MGR各节点的状态:

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 | 3460f111-9314-11ee-a532-000c295df6cf | mgr1        |        3306 | ONLINE       | SECONDARY   | 8.0.30         | XCom                       |
| group_replication_applier | 52854f96-9314-11ee-8821-000c29ced34f | mgr2        |        3306 | ONLINE       | SECONDARY   | 8.0.30         | XCom                       |
| group_replication_applier | 70fa199f-9314-11ee-a8eb-000c29f957d2 | mgr3        |        3306 | ONLINE       | PRIMARY     | 8.0.30         | XCom                       |
+---------------------------+--------------------------------------+-------------+-------------+--------------+-------------+----------------+----------------------------+
3 rows in set (0.01 sec)

 输出结果中主要几个列的解读如下:

  • MEMBER_ID 列值就是各节点的 server_uuid,用于唯一标识每个节点,在命令行模式下,调用 udf 时传入 MEMBER_ID 以指定各节点。

  • MEMBER_ROLE 表示各节点的角色,如果是 PRIMARY 则表示该节点可接受读写事务,如果是 SECONDARY 则表示该节点只能接受只读事务。如果只有一个节点是 PRIMARY,其余都是 SECONDARY,则表示当前处于 单主模式;如果所有节点都是 PRIMARY,则表示当前处于 多主模式

  • MEMBER_STATE

    表示各节点的状态,共有几种状态:ONLINE、RECOVERING、OFFLINE、ERROR、UNREACHABLE 等,下面分别介绍几种状态。

    • ONLINE,表示节点处于正常状态,可提供服务。

    • RECOVERING,表示节点正在进行分布式恢复,等待加入集群,这时候有可能正在从donor节点利用clone复制数据,或者传输binlog中。

    • OFFLINE,表示该节点当前处于离线状态。提醒,在正要加入或重加入集群时,可能也会有很短瞬间的状态显示为 OFFLINE。

    • ERROR,表示该节点当前处于错误状态,无法成为集群的一员。当节点正在进行分布式恢复或应用事务时,也是有可能处于这个状态的。当节点处于ERROR状态时,是无法参与集群事务裁决的。节点正在加入或重加入集群时,在完成兼容性检查成为正式MGR节点前,可能也会显示为ERROR状态。

    • UNREACHABLE,当组通信消息收发超时时,故障检测机制会将本节点标记为怀疑状态,怀疑其可能无法和其他节点连接,例如当某个节点意外断开连接时。当在某个节点上看到其他节点处于 UNREACHABLE 状态时,有可能意味着此时部分节点发生了网络分区,也就是多个节点分裂成两个或多个子集,子集内的节点可以互通,但子集间无法互通。

当节点的状态不是 ONLINE 时,就应当立即发出告警并检查发生了什么。

在节点状态发生变化时,或者有节点加入、退出时,表 performance_schema.replication_group_members 的数据都会更新,各节点间会交换和共享这些状态信息,因此可以在任意节点查看。

2. MGR事务状态监控

另一个需要重点关注的是Secondary节点的事务状态,更确切的说是关注待认证事务及待应用事务队列大小。

可以执行下面的命令查看当前除了 PRIMARY 节点外,其他节点的 trx_tobe_certifiedrelaylog_tobe_applied 值是否较大:

mysql> SELECT MEMBER_ID AS id, COUNT_TRANSACTIONS_IN_QUEUE AS trx_tobe_certified, COUNT_TRANSACTIONS_REMOTE_IN_APPLIER_QUEUE AS relaylog_tobe_applied, COUNT_TRANSACTIONS_CHECKED AS trx_chkd, COUNT_TRANSACTIONS_REMOTE_APPLIED AS trx_done, COUNT_TRANSACTIONS_LOCAL_PROPOSED AS proposed FROM performance_schema.replication_group_member_stats;
+--------------------------------------+--------------------+-----------------------+----------+----------+----------+
| id                                   | trx_tobe_certified | relaylog_tobe_applied | trx_chkd | trx_done | proposed |
+--------------------------------------+--------------------+-----------------------+----------+----------+----------+
| 3460f111-9314-11ee-a532-000c295df6cf |                  0 |                     0 |        3 |        3 |        3 |
| 52854f96-9314-11ee-8821-000c29ced34f |                  0 |                     0 |        3 |        4 |        0 |
| 70fa199f-9314-11ee-a8eb-000c29f957d2 |                  0 |                     0 |        3 |        3 |        0 |
+--------------------------------------+--------------------+-----------------------+----------+----------+----------+
3 rows in set (0.01 sec)

其中,relaylog_tobe_applied 的值表示远程事务写到relay log后,等待回放的事务队列,trx_tobe_certified 表示等待被认证的事务队列大小,这二者任何一个值大于0,都表示当前有一定程度的延迟。

还可以通过关注上述两个数值的变化,看看两个队列是在逐步加大还是缩小,据此判断Primary节点是否"跑得太快"了,或者Secondary节点是否"跑得太慢"。

多提一下,在启用流控(flow control)时,上述两个值超过相应的阈值时(group_replication_flow_control_applier_threshold 和 group_replication_flow_control_certifier_threshold 默认阈值都是 25000),就会触发流控机制

3. 其他监控

另外,也可以查看接收到的事务和已执行完的事务之间的差距来判断:

mysql> SELECT RECEIVED_TRANSACTION_SET FROM performance_schema.replication_connection_status WHERE  channel_name = 'group_replication_applier' UNION ALL SELECT variable_value FROM performance_schema.global_variables WHERE  variable_name = 'gtid_executed'\G
*************************** 1. row ***************************
RECEIVED_TRANSACTION_SET: 5dbabbe6-8050-49a0-9131-1de449167446:1-6
*************************** 2. row ***************************
RECEIVED_TRANSACTION_SET: 5dbabbe6-8050-49a0-9131-1de449167446:1-6
2 rows in set (0.01 sec)

四、利用MySQL Router构建读写分离MGR集群

本文介绍如何在MGR集群前端部署MySQL Router以实现读写分离、读负载均衡,以及故障自动转移。

MySQL Router是一个轻量级的中间件,它采用多端口的方案实现读写分离以及读负载均衡,而且同时支持mysql和mysql x协议。

建议把MySQL Router部署在应用服务器上,每个应用服务器都部署一套,这样应用程序可以直接连接本机IP,连接的效率更高,而且后端数据库发生变化时,程序端也无需修改IP配置。

1. 部署MySQL Router

MySQL Router第一次启动时要先初始化:

[root@proxy ~]# yum install mysql-router-community-8.0.35-1.el7.x86_64.rpm

 2. 启动mysqlrouter服务

这就初始化完毕了,按照上面的提示,直接启动 mysqlrouter 服务即可

[root@proxy ~]# systemctl enable --now mysqlrouter.service
Created symlink from /etc/systemd/system/multi-user.target.wants/mysqlrouter.service to /usr/lib/systemd/system/mysqlrouter.service.

[root@proxy ~]# ps -ef | grep -v grep | grep mysqlrouter
mysqlro+   1461      1  0 11:38 ?        00:00:00 /usr/bin/mysqlrouter

可以看到 mysqlrouter 服务正常启动了。

mysqlrouter 初始化时自动生成的配置文件是 /etc/mysqlrouter/mysqlrouter.conf,主要是关于R/W、RO不同端口的配置,例如:

cat >> /etc/mysqlrouter/mysqlrouter.conf    <<  EOF
[routing:write]
bind_address = 192.168.150.24
bind_port = 8001
mode = read-write
destinations = 192.168.150.21:3306
[routing:blanace]
bind_address = 192.168.150.24
bind_port = 8002
mode = read-only
destinations = 192.168.150.22:3306,192.168.150.23:3306
EOF

[root@proxy ~]# systemctl restart mysqlrouter.service

3. 确认读写分离效果

创建用户

mysql> create user admin@'192.168.150.%' identified with mysql_native_password by '123456';
Query OK, 0 rows affected (0.00 sec)
​
mysql> grant all on *.* to admin@'192.168.150.%';
Query OK, 0 rows affected (0.01 sec)

现在,用客户端连接到6446(读写)端口,确认连接的是PRIMARY节点:

[root@mgr1 ~]# mysql -uadmin -p123456 -h192.168.150.24 -P8001
Enter password:
...
#记住下面几个 MEMBER_ID
mysql> select MEMBER_ID,MEMBER_ROLE from performance_schema.replication_group_members;
+--------------------------------------+-------------+
| MEMBER_ID                            | MEMBER_ROLE |
+--------------------------------------+-------------+
| 3460f111-9314-11ee-a532-000c295df6cf | SECONDARY   |
| 52854f96-9314-11ee-8821-000c29ced34f | SECONDARY   |
| 70fa199f-9314-11ee-a8eb-000c29f957d2 | PRIMARY     |
+--------------------------------------+-------------+
3 rows in set (0.00 sec)

mysql> select @@server_uuid;
+--------------------------------------+
| @@server_uuid                        |
+--------------------------------------+
| 3460f111-9314-11ee-a532-000c295df6cf |
+--------------------------------------+
1 row in set (0.00 sec)
# 确实是连接的PRIMARY节点

 同样地,连接8002(只读)端口,确认连接的是SECONDARY节点:

[root@mgr2 ~]# mysql -uadmin -p123456 -h192.168.150.24 -P8002
Enter password:
...
mysql> select @@server_uuid;
+--------------------------------------+
| @@server_uuid                        |
+--------------------------------------+
| 52854f96-9314-11ee-8821-000c29ced34f |
+--------------------------------------+
1 row in set (0.00 sec)

# 确实是连接的SECONDARY节点

4. 确认只读负载均衡效果

MySQL Router连接读写节点(Primary节点)默认的策略是 first-available,即只连接第一个可用的节点。Router连接只读节点(Secondary节点)默认的策略是 round-robin-with-fallback,会在各个只读节点间轮询。

保持8002端口原有的连接不退出,继续新建到8002端口的连接,查看 server_uuid,这时应该会发现读取到的是其他只读节点的值,因为 mysqlrouter 的读负载均衡机制是在几个只读节点间自动轮询。在默认的 round-robin-with-fallback 策略下,只有当所有只读节点都不可用时,只读请求才会打到PRIMARY节点上。

[root@mgr3 ~]# mysql -uadmin -p123456 -h192.168.150.24 -P8002
mysql> select @@server_uuid;
+--------------------------------------+
| @@server_uuid                        |
+--------------------------------------+
| 70fa199f-9314-11ee-a8eb-000c29f957d2 |
+--------------------------------------+
1 row in set (0.00 sec)