Mysql5

发布时间 2023-03-23 17:09:06作者: Austines
title: Mysql5.7 MGR模式
date: 2022-08-26
tags:
  - Linux
  - Mysql
  - MGR
categories: 
- 运维
- 数据库
- Mysql
- MGR同步
keywords: 'Linux,Mysql,MGR'
description: Mysql5.7 MGR模式
cover: https://qiufuqi.gitee.io/img/hexo/MGR.jpg
abbrlink: mysql5.7_MGR
comments: false

MGR简介

MySQL Group Replication,简称MGR,它是MySQL官方推出的基于paxos分布式一致性协议的状态机复制,实现了分布式下数据的最终一致性。同时MGR提供了高可用、高扩展、高可靠的MySQL集群解决方案,它也是金融级分布式数据库之一。

MGR适用场景

MGR天生就是为金融场景设计的,例如:支付,证券交易,保险,银行等等。因为这些场景要求数据必须做到零丢失,数据库可用性在4个9,甚至5个9(年度停机时间不超过5分钟)。
MGR采用多副本,在2N+1个节点集群中,集群只要N +1个节点还存活着,数据库就能稳定的对外提供服务。

MGR运行模式

MGR运行模式有2种:
单主模式(single-primary mode)
多主模式(multi-primary mode)

单主模式:

在这种模式下,组具有设置为读写模式的单主服务器。该组中的所有其他成员都设置为只读模式。这会自动发生。主服务器通常是引导该组的第一台服务器,所有其他加入的服务器会自动了解主服务器,并设置为只读。

多主模式:

在多主要模式下,没有单个主要概念。无需参与选举程序,因为没有服务器扮演任何特殊角色,所有服务器均设置为读写模式。

MGR选举原理

MGR单主模式选举原理

单主模式下,如果主节点挂了,那么其他的成员会自动选举出新的主成员,成员之间可以通过配置权重来确定下一个主成员是谁,如果没有配置权重,则会对所有在线成员的UUID进行排序,然后选取UUID最小的成员作为主成员。

MGR多主模式选举原理

多主模式,所有的组内成员对外提供读写服务,是真正意义上的并发,MGR对于高并发有很好的的处理能力。多主模式下,组内所有成员没有主从之分,对用户来说,就像在操作一个MySQL一样。所以在多主模式下,不存在选举主节点,因为所有节点都是主节点。

MGR复制原理

在2N+1个节点组成的单主模式组复制集群中,主库上一个事务提交时,会将事务修改记录相关的信息和事务产生的BINLOG事件打包生成一个写集(WRITE SET),将写集发送给所有节点,并通过至少N个节点投票通过才能事务提交成功。

MGR组复制的特点

  • 高一致性:基于分布式paxos协议实现组复制,保证数据一致性;
  • 高容错性:自动检测机制,只要不是大多数节点都宕机就可以继续工作,内置防脑裂保护机制;
  • 高扩展性:节点的增加与移除会自动更新组成员信息,新节点加入后,自动从其他节点同步增量数据,直到与其他节点数据一致;
  • 高灵活性:提供单主模式和多主模式,单主模式在主库宕机后能够自动选主,所有写入都在主节点进行,多主模式支持多节点写入。

示例图

MGR要求

1.必须适用innodb存储引擎
2.创建的业务表,必须要有主键
3.MGR必须适用IPv4网络,不支持IPv6
4.MGR复制网络必须和业务网络隔离
5.binlog日志格式必须为row模式
6.关闭二进制日志校验和,设置--binlog-checksum=NONE
7.小写 table 格名称. 在所有组成员上将--lower-case-table-names设置为相同的值
8.隔离级别设置为RC

MGR限制

1.MGR不支持SERIALIZABLE 隔离级别
2.MGR集群节点不能超过9
3.MGR不支持大事务,事务大小最好不超过143MB,当事务过大,无法在5 秒的时间内通过网络在组成员之间复制消息,则可能会怀疑成员失败了,然后将其驱逐出局。
4.并发 DDL 与 DML 操作. 当使用多主模式时,不支持针对同一对象但在不同服务器上执行的并发数据定义语句和数据操作语句。
5.对表的级联约束的外键支持不好,不建议适用。

MGR模式实现

环境准备

# 三台服务器
10.128.1.41   MGR-node1   server_id=1
10.128.1.42   MGR-node2   server_id=2
10.128.1.43   MGR-node3   server_id=3

# 为了实验方便,关闭所有节点防火墙
[root@localhost ~]# systemctl stop firewalld

# 关闭selinux
[root@localhost ~]# vi /etc/sysconfig/selinux
SELINUX=disabled

[root@localhost ~]# setenforce 0

# 修改各个节点名称
[root@localhost ~]# hostnamectl set-hostname MGR-node1
[root@localhost ~]# hostname -f

# 特别要注意一个关键点: 必须保证各个mysql节点的主机名不一致,并且能通过主机名找到各成员!
# 则必须要在每个节点的/etc/hosts里面做主机名绑定,否则后续将节点加入group组会失败!报错RECOVERING!!
[root@localhost ~]# vi /etc/hosts
10.128.1.41     MGR-node1
10.128.1.42     MGR-node2
10.128.1.43     MGR-node3

节点MySQL5.7安装

MySQL5.7安装请参考:安装步骤

MGR信息安装和配置

# 1.配置所有节点的组复制信息 
# 重新编辑my.cnf
# MGR-node1节点
[root@mgr-node1 ~]# cp /etc/my.cnf /etc/my.cnf.bak
[root@mgr-node1 ~]# >/etc/my.cnf
[mysqld]
datadir = /var/lib/mysql
socket = /var/lib/mysql/mysql.sock

symbolic-links = 0

log-error = /var/log/mysqld.log
pid-file = /var/run/mysqld/mysqld.pid
 
# 复制框架
server_id=1
gtid_mode=ON
enforce_gtid_consistency=ON
binlog_checksum=NONE
 
log_bin=binlog
log_slave_updates=ON
binlog_format=ROW
master_info_repository=TABLE
relay_log_info_repository=TABLE
 
# 组复制设置
# server必须为每个事务收集写集合,并使用XXHASH64哈希算法将其编码为散列
transaction_write_set_extraction=XXHASH64
# 告知插件加入或创建组命名,UUID
loose-group_replication_group_name="aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa"
# server启动时不自启组复制,为了避免每次启动自动引导具有相同名称的第二个组,所以设置为OFF。
loose-group_replication_start_on_boot=off
# 告诉插件使用IP地址,端口24901用于接收组中其他成员转入连接
loose-group_replication_local_address="10.128.1.41:24901"
# 启动组server,种子server,加入组应该连接这些的ip和端口;其他server要加入组得由组成员同意
loose-group_replication_group_seeds="10.128.1.41:24901,10.128.1.42:24901,10.128.1.43:24901"
loose-group_replication_bootstrap_group=off
report_host=10.128.1.41
report_port=3306

# 完成上述配置后,将MGR-node1节点的/etc/my.cnf拷贝到其他节点 (所有节点都要安装rsync)
[root@MGR-node1 ~]# rsync -e "ssh -p22" -avpgolr /etc/my.cnf root@10.128.1.42:/etc/
[root@MGR-node1 ~]# rsync -e "ssh -p22" -avpgolr /etc/my.cnf root@10.128.1.43:/etc/

# 3个MGR节点除了server_id、loose-group_replication_local_address、report_host 三个参数不一样外,其他保持一致。
# 自行修改 server_id、loose-group_replication_local_address、report_host

####################################################################################
# 2.配置完成后,启动一次数据库,安装MGR插件,设置复制账号(所有MGR节点都要执行)
[root@mgr-node1 ~]# systemctl restart mysqld
[root@mgr-node1 ~]# mysql -uroot -p

mysql> INSTALL PLUGIN group_replication SONAME 'group_replication.so';
Query OK, 0 rows affected (0.08 sec)

mysql> SET SQL_LOG_BIN=0;
Query OK, 0 rows affected (0.00 sec)

# 降低密码策略 可不做
mysql> set global validate_password_policy=0;
Query OK, 0 rows affected (0.00 sec)

mysql> set global validate_password_length=1;
Query OK, 0 rows affected (0.00 sec)

# 创建mgr_user用户 密码123456
mysql> CREATE USER mgr_user@'%' IDENTIFIED BY '123456';
Query OK, 0 rows affected (0.00 sec)

mysql> GRANT REPLICATION SLAVE ON *.* TO mgr_user@'%';
Query OK, 0 rows affected (0.00 sec)

mysql> flush privileges;
Query OK, 0 rows affected (0.00 sec)

mysql> set SQL_LOG_BIN=1;
Query OK, 0 rows affected (0.00 sec)

mysql> CHANGE MASTER TO MASTER_USER='mgr_user', MASTER_PASSWORD='123456' FOR CHANNEL 'group_replication_recovery';
Query OK, 0 rows affected, 2 warnings (0.25 sec)

启动MGR单主模式

# 1.启动MGR,在主库(10.128.1.41)节点上执行
[root@mgr-node1 ~]# mysql -uroot -p

mysql> SET GLOBAL group_replication_bootstrap_group=ON;
Query OK, 0 rows affected (0.00 sec)

mysql> START GROUP_REPLICATION;
Query OK, 0 rows affected (2.41 sec)

mysql> SET GLOBAL group_replication_bootstrap_group=OFF;
Query OK, 0 rows affected (0.00 sec)

查看MGR组信息
mysql> SELECT * FROM performance_schema.replication_group_members;
+---------------------------+--------------------------------------+-------------+-------------+--------------+
| CHANNEL_NAME              | MEMBER_ID                            | MEMBER_HOST | MEMBER_PORT | MEMBER_STATE |
+---------------------------+--------------------------------------+-------------+-------------+--------------+
| group_replication_applier | 7bae1d67-244f-11ed-8a33-525400f0bd77 | 10.128.1.41 |        3306 | ONLINE       |
+---------------------------+--------------------------------------+-------------+-------------+--------------+
1 row in set (0.00 sec)

# 2.在其他节点加入MGR集群(从节点执行)
[root@mgr-node2 ~]# mysql -uroot -p

mysql> START GROUP_REPLICATION;
Query OK, 0 rows affected (6.18 sec)

# 如果失败 将允许加入打开
mysql> set global group_replication_allow_local_disjoint_gtids_join=ON;

mysql> START GROUP_REPLICATION;
Query OK, 0 rows affected (6.18 sec)

# 再次查看MGR组信息
mysql> SELECT * FROM performance_schema.replication_group_members;
+---------------------------+--------------------------------------+-------------+-------------+--------------+
| CHANNEL_NAME              | MEMBER_ID                            | MEMBER_HOST | MEMBER_PORT | MEMBER_STATE |
+---------------------------+--------------------------------------+-------------+-------------+--------------+
| group_replication_applier | 12e71e02-245e-11ed-9865-5254005d95d4 | 10.128.1.42 |        3306 | ONLINE       |
| group_replication_applier | 32476ac2-251b-11ed-84c9-5254002932f8 | 10.128.1.43 |        3306 | ONLINE       |
| group_replication_applier | 7bae1d67-244f-11ed-8a33-525400f0bd77 | 10.128.1.41 |        3306 | ONLINE       |
+---------------------------+--------------------------------------+-------------+-------------+--------------+
3 rows in set (0.00 sec)

# 三个MGR节点状态为online,并且主节点为10.128.1.41,只有主节点可以写入,其他两个MGR节点只读,MGR单主模式搭建成功。

# 如果新加入的节点状态为RECOVERING,查看日志
[root@MGR-node3 ~]# tail -2000 /var/log/mysqld.log

2022-08-26T09:15:35.146740Z 734 [ERROR] Slave I/O for channel 'group_replication_recovery': Got fatal error 1236 from master when
reading data from binary log: 'The slave is connecting using CHANGE MASTER TO MASTER_AUTO_POSITION = 1, but the master has
purged binary logs containing GTIDs that the slave requires.', Error_code: 1236

解决方法:
登录主库10.128.1.41,查看purge的GTID:
[root@mgr-node1 ~]# mysql -uroot -p
mysql> show global variables like 'gtid_purged';
+---------------+------------------------------------------+
| Variable_name | Value                                    |
+---------------+------------------------------------------+
| gtid_purged   | 8769f936-3e51-11e9-acaa-005056ac6820:1-2 |
+---------------+------------------------------------------+
1 row in set (0.00 sec)
  
接着在两个从库10.128.1.42, 10.128.1.43的数据库上执行下面命令,即跳过这个GTID:
mysql> STOP GROUP_REPLICATION;
Query OK, 0 rows affected (10.14 sec)
  
mysql> reset master;
Query OK, 0 rows affected (0.06 sec)
  
mysql> set global gtid_purged = '8769f936-3e51-11e9-acaa-005056ac6820:1-2';
Query OK, 0 rows affected (0.24 sec)
  
mysql>  START GROUP_REPLICATION;
Query OK, 0 rows affected, 1 warning (3.49 sec)
  
# 再次查看查看MGR组信息 (在三个MGR节点上都可以查看),
mysql> SELECT * FROM performance_schema.replication_group_members;
+---------------------------+--------------------------------------+-------------+-------------+--------------+
| CHANNEL_NAME              | MEMBER_ID                            | MEMBER_HOST | MEMBER_PORT | MEMBER_STATE |
+---------------------------+--------------------------------------+-------------+-------------+--------------+
| group_replication_applier | 12e71e02-245e-11ed-9865-5254005d95d4 | 10.128.1.42 |        3306 | ONLINE       |
| group_replication_applier | 32476ac2-251b-11ed-84c9-5254002932f8 | 10.128.1.43 |        3306 | ONLINE       |
| group_replication_applier | 7bae1d67-244f-11ed-8a33-525400f0bd77 | 10.128.1.41 |        3306 | ONLINE       |
+---------------------------+--------------------------------------+-------------+-------------+--------------+

# 查看当前主节点
mysql> SHOW STATUS LIKE 'group_replication_primary_member';
+----------------------------------+--------------------------------------+
| Variable_name                    | Value                                |
+----------------------------------+--------------------------------------+
| group_replication_primary_member | 7bae1d67-244f-11ed-8a33-525400f0bd77 |
+----------------------------------+--------------------------------------+
1 row in set (0.01 sec)
# 查看主键
mysql> SELECT * FROM performance_schema.replication_group_members WHERE MEMBER_ID = (SELECT VARIABLE_VALUE FROM performance_schema.global_status WHERE VARIABLE_NAME= 'group_replication_primary_member');
+---------------------------+--------------------------------------+-------------+-------------+--------------+
| CHANNEL_NAME              | MEMBER_ID                            | MEMBER_HOST | MEMBER_PORT | MEMBER_STATE |
+---------------------------+--------------------------------------+-------------+-------------+--------------+
| group_replication_applier | 7bae1d67-244f-11ed-8a33-525400f0bd77 | 10.128.1.41 |        3306 | ONLINE       |
+---------------------------+--------------------------------------+-------------+-------------+--------------+

# 创建数据库进行测试,只有主库才能进行写操作

# 表主键自增每次7
mysql> show variables like 'auto%';
+--------------------------+-------+
| Variable_name            | Value |
+--------------------------+-------+
| auto_generate_certs      | ON    |
| auto_increment_increment | 7     |
| auto_increment_offset    | 1     |
| autocommit               | ON    |
| automatic_sp_privileges  | ON    |
+--------------------------+-------+
5 rows in set (0.01 sec)

# 修改每次自增数值 尽量不要该
mysql> SET @@auto_increment_increment=10;

MGR切换多主模式

MGR切换模式需要重新启动组复制,因些需要在所有节点上先关闭组复制,设置 group_replication_single_primary_mode=OFF 等参数,再启动组复制。

# 1.所有节点执行
mysql> stop group_replication;
Query OK, 0 rows affected (9.32 sec)

mysql> set global group_replication_single_primary_mode=OFF;
Query OK, 0 rows affected (0.00 sec)

mysql> set global group_replication_enforce_update_everywhere_checks=ON;
Query OK, 0 rows affected (0.01 sec)

# 2.任意一个节点执行
mysql> SET GLOBAL group_replication_bootstrap_group=ON;
Query OK, 0 rows affected (0.01 sec)

mysql> START GROUP_REPLICATION;
Query OK, 0 rows affected (2.19 sec)

mysql> SET GLOBAL group_replication_bootstrap_group=OFF;
Query OK, 0 rows affected (0.00 sec)

# 3.其他节点执行
mysql> START GROUP_REPLICATION;

# 4.查看MGR组信息
mysql> SELECT * FROM performance_schema.replication_group_members;
+---------------------------+--------------------------------------+-------------+-------------+--------------+
| CHANNEL_NAME              | MEMBER_ID                            | MEMBER_HOST | MEMBER_PORT | MEMBER_STATE |
+---------------------------+--------------------------------------+-------------+-------------+--------------+
| group_replication_applier | 12e71e02-245e-11ed-9865-5254005d95d4 | 10.128.1.42 |        3306 | ONLINE       |
| group_replication_applier | 32476ac2-251b-11ed-84c9-5254002932f8 | 10.128.1.43 |        3306 | ONLINE       |
| group_replication_applier | 7bae1d67-244f-11ed-8a33-525400f0bd77 | 10.128.1.41 |        3306 | ONLINE       |
+---------------------------+--------------------------------------+-------------+-------------+--------------+
3 rows in set (0.00 sec)

# 创建数据库进行测试,所有节点都进行写入操作

MGR切换单主模式

# 1.停止组复制(所有节点执行)
mysql> stop group_replication;
Query OK, 0 rows affected (9.68 sec)

mysql> set global group_replication_enforce_update_everywhere_checks=OFF;
Query OK, 0 rows affected (0.01 sec)

mysql> set global group_replication_single_primary_mode=ON;
Query OK, 0 rows affected (0.01 sec)

# 2.选择一个主节点执行
mysql> SET GLOBAL group_replication_bootstrap_group=ON;
Query OK, 0 rows affected (0.00 sec)

mysql> START GROUP_REPLICATION;
Query OK, 0 rows affected (2.18 sec)

mysql> SET GLOBAL group_replication_bootstrap_group=OFF;
Query OK, 0 rows affected (0.00 sec)

# 3.其他节点执行
mysql> START GROUP_REPLICATION;
Query OK, 0 rows affected (6.22 sec)

# 4.查看MGR组信息
mysql> SELECT * FROM performance_schema.replication_group_members;
+---------------------------+--------------------------------------+-------------+-------------+--------------+
| CHANNEL_NAME              | MEMBER_ID                            | MEMBER_HOST | MEMBER_PORT | MEMBER_STATE |
+---------------------------+--------------------------------------+-------------+-------------+--------------+
| group_replication_applier | 12e71e02-245e-11ed-9865-5254005d95d4 | 10.128.1.42 |        3306 | ONLINE       |
| group_replication_applier | 32476ac2-251b-11ed-84c9-5254002932f8 | 10.128.1.43 |        3306 | ONLINE       |
| group_replication_applier | 7bae1d67-244f-11ed-8a33-525400f0bd77 | 10.128.1.41 |        3306 | ONLINE       |
+---------------------------+--------------------------------------+-------------+-------------+--------------+
3 rows in set (0.00 sec)

# 查看当前主节点
mysql> SHOW STATUS LIKE 'group_replication_primary_member';
+----------------------------------+--------------------------------------+
| Variable_name                    | Value                                |
+----------------------------------+--------------------------------------+
| group_replication_primary_member | 12e71e02-245e-11ed-9865-5254005d95d4 |
+----------------------------------+--------------------------------------+
1 row in set (0.01 sec)

# 至此切换为单主模式

故障恢复

# 1.单主模式
# 如果主节点挂掉,通过选举程序会从从库节点选择一个作为主节点

# 关闭主节点mgr-node1的mysqld服务
[root@mgr-node1 ~]# systemctl stop mysqld

# 在其他节点查看MGR信息
mysql> SELECT * FROM performance_schema.replication_group_members;
+---------------------------+--------------------------------------+-------------+-------------+--------------+
| CHANNEL_NAME              | MEMBER_ID                            | MEMBER_HOST | MEMBER_PORT | MEMBER_STATE |
+---------------------------+--------------------------------------+-------------+-------------+--------------+
| group_replication_applier | 12e71e02-245e-11ed-9865-5254005d95d4 | 10.128.1.42 |        3306 | ONLINE       |
| group_replication_applier | 32476ac2-251b-11ed-84c9-5254002932f8 | 10.128.1.43 |        3306 | ONLINE       |
+---------------------------+--------------------------------------+-------------+-------------+--------------+
2 rows in set (0.00 sec)

# 尝试在mgr-node2节点数据库更新数据,发现可以操作

# mgr-node1节点恢复后,需要手动激活该节点的组复制功能
[root@mgr-node1 ~]# systemctl start mysqld
[root@mgr-node1 ~]# mysql -uroot -p

mysql> start group_replication;
Query OK, 0 rows affected (3.55 sec)

mysql> SELECT * FROM performance_schema.replication_group_members;
+---------------------------+--------------------------------------+-------------+-------------+--------------+
| CHANNEL_NAME              | MEMBER_ID                            | MEMBER_HOST | MEMBER_PORT | MEMBER_STATE |
+---------------------------+--------------------------------------+-------------+-------------+--------------+
| group_replication_applier | 12e71e02-245e-11ed-9865-5254005d95d4 | 10.128.1.42 |        3306 | ONLINE       |
| group_replication_applier | 32476ac2-251b-11ed-84c9-5254002932f8 | 10.128.1.43 |        3306 | ONLINE       |
| group_replication_applier | 7bae1d67-244f-11ed-8a33-525400f0bd77 | 10.128.1.41 |        3306 | ONLINE       |
+---------------------------+--------------------------------------+-------------+-------------+--------------+
3 rows in set (0.00 sec)

# 查看当前主节点
mysql> SHOW STATUS LIKE 'group_replication_primary_member';
+----------------------------------+--------------------------------------+
| Variable_name                    | Value                                |
+----------------------------------+--------------------------------------+
| group_replication_primary_member | 12e71e02-245e-11ed-9865-5254005d95d4 |
+----------------------------------+--------------------------------------+
1 row in set (0.01 sec)

# mgr-node1恢复后变成了从库节点,只能读不能写。

# 2.多主模式
# 如果某个节点挂了, 则其他的节点继续进行同步.
# 当故障节点恢复后, 只需要手动激活下该节点的组复制功能("START GROUP_REPLICATION;"),
# 即可正常加入到MGR组复制集群内并自动同步其他节点数据.