MySQL集群高可用架构——组复制 (MGR)
MySQL集群高可用架构——组复制
- 一、概念
- 二、流程
- 三、组复制单主和多主模式
- 四、实现mysql组复制-单主模式
- 1、环境说明
- 2、主库配置
- 3、从库配置
- 4、验证结果
- 五、实现mysql组复制-多主模式
- 1、基本配置
- 2、验证结果
一、概念
MySQL Group Replication(简称 MGR )是 MySQL 官方于 2016 年 12 月推出的一个全新的高可用与高扩展的解决方案。
组复制是 MySQL 5.7.17 版本出现的新特性,它提供了高可用、高扩展、高可靠的 MySQL 集群服务。
MySQL 组复制分单主模式和多主模式,传统的mysql复制技术仅解决了数据同步的问题,MGR 对属于同一组的服务器自动进行协调。对于要提交的事务,组成员必须就全局事务序列中给定事务的顺序达成一致,提交或回滚事务由每个服务器单独完成,但所有服务器都必须做出相同的决定,如果存在网络分区,导致成员无法达成事先定义的分割策略,则在解决此问题之前系统不会继续进行,直到网络问题解决,这是一种内置的脑裂保护机制。
MGR由组通信系统( Group Communication System , GCS ) 协议支持该系统提供故障检测机制、组成员服务以及安全且有序的消息传递。
二、流程
首先我们将多个节点共同组成一个复制组,在执行读写(RW)事务的时候,需要通过一致性协议层(Consensus 层)的同意,也就是读写事务想要进行提交,必须要经过组里“大多数人”(对应 Node 节点)的同意,大多数指的是同意的节点数量需要大于 (N/2+1),这样才可以进行提交,而不是原发起方一个说了算。而针对只读(RO)事务则不需要经过组内同意,直接 提交 即可 。
三、组复制单主和多主模式
single-primary mode(单写或单主模式)
单写模式 group 内只有一台节点可写可读,其他节点只可以读。当主服务器失败时,会自动选择新的主服务器。
multi-primary mode(多写或多主模式)
组内的所有机器都是 primary 节点,同时可以进行读写操作,并且数据是最终一致的。
四、实现mysql组复制-单主模式
1、环境说明
主机名 | ip | 操作系统版本 | mysql版本 |
---|---|---|---|
master | 192.168.83.138/24 | rhel7.9 | mysql8.0.40 |
rep1 | 192.168.83.139/24 | rhel7.9 | mysql8.0.40 |
rep2 | 192.168.83.140/24 | rhel7.9 | mysql8.0.40 |
https://dev.mysql.com/doc/refman/8.0/en/group-replication-configuring-instances.html
所有主机上配置域名自解析:
# 三个主机均需要配置hosts文件的解析,如果不配置域名解析则需要在/etc/my.cnf中加一条配置skip-name-resolve
[root@node1 ~]# cat /etc/hosts
192.168.83.138 master
192.168.83.139 rep1
192.168.83.140 rep2
2、主库配置
2.1 修改配置文件
#1、修改配置文件
[root@master ~]# vim /etc/my.cnf
[mysqld]
datadir=/data/mysql
socket=/data/mysql/mysql.sock
log_timestamps=SYSTEM #设置日志时间和本地时间保持一致
server_id=138
disabled_storage_engines="MyISAM,BLACKHOLE,FEDERATED,ARCHIVE,MEMORY" #组复制,数据必须存储在 InnoDB 事务存储引擎中
gtid_mode=ON #组复制要开启gtid
enforce_gtid_consistency=ON
log_bin=binlog #默认开启
log_slave_updates=ON #默认开启
binlog_format=ROW #默认开启
transaction_write_set_extraction=XXHASH64 #默认开启,组复制使用此信息在所有组成员上进行冲突检测
plugin_load_add='group_replication.so' #将组复制插件添加到服务器启动时加载的插件列表中
group_replication_group_name="aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa" #告诉插件它正在加入或创建的组名为“aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaa”
group_replication_start_on_boot=off #插件在服务器启动时不自动启动操作,使用手动启动插件
group_replication_local_address= "192.168.83.138:33061" #与其它主机通信时使用的网络地址和端口
group_replication_group_seeds= "192.168.83.138:33061,192.168.83.139:33061,192.83.168.140:33061" #设置组成员的主机名和端口
group_replication_bootstrap_group=off #指示插件是否启动该组,在首次引导组时在一个服务器上启用
group_replication_ip_whitelist="192.168.168.0/24,127.0.0.1/8" #仅允许白名单内的 IP 加入复制组
group_replication_recovery_use_ssl=on #caching_sha2_password插件要求安全传输密码,开启主从之间的连接使用SSL/TLS #2、去除注释信息
[root@master ~]# sed -i 's/#.*//' /etc/my.cnf#3、重启服务
[root@master ~]# /etc/init.d/mysqld restart
2.2 在主的数据库中添加复制账号并授予权限
#1、在主的数据库中添加复制账号并授予权限,从上面也需要设置一样的账号
SET SQL_LOG_BIN=0;
CREATE USER rp@'%' IDENTIFIED BY '123';
GRANT REPLICATION SLAVE ON *.* TO rp@'%';
GRANT CONNECTION_ADMIN ON *.* TO rp@'%';
GRANT BACKUP_ADMIN ON *.* TO rp@'%';
GRANT GROUP_REPLICATION_STREAM ON *.* TO rp@'%';
FLUSH PRIVILEGES;
SET SQL_LOG_BIN=1;
CHANGE REPLICATION SOURCE TO SOURCE_USER='rp', SOURCE_PASSWORD='123' FOR CHANNEL 'group_replication_recovery';
# 注意:如果需要重置则使用命令reset master;#2、查看是否有group_replication插件
mysql> show plugins;
| group_replication | ACTIVE | GROUP REPLICATION | group_replication.so | GPL |#3、启动MGR集群
# 使用当前服务器作为引导服务器启动一个新的群组复制过程或者恢复一个已经存在的群组
SET GLOBAL group_replication_bootstrap_group=ON;
START GROUP_REPLICATION USER='rp',PASSWORD='123';
SET GLOBAL group_replication_bootstrap_group=OFF;#4、在主上查看组信息
mysql> SELECT * FROM performance_schema.replication_group_members;
说明:
CHANNEL_NAME:通道名称。组复制插件创建两个复制通道:
group_replication_recovery:用于与分布式恢复阶段相关的复制更改。
group_replication_applier:用于来自组传入的更改,是应用直接来自组的事务的通道。
MEMBER_ID:组成员实例的server_uuid。
MEMBER_HOST:组成员主机名。如果配置了report_host参数,这里显示IP地址。
MEMBER_ROLE:成员角色,主为PRIMARY,从为SECONDARY。
MEMBER_VERSION:成员数据库实例版本。
MEMBER_STATE:成员状态,取值和含义如下所示:
ONLINE 表示该成员可正常提供服务
RECOVERING 表示当前成员正在从其它节点恢复数据
OFFLINE 表示组复制插件已经加载,但是该成员不属于任何一个复制组
ERROR 表示成员在recovery阶段出现错误或者从其它节点同步状态中出现错误
UNREACHABLE 成员处于不可达状态,无法与之进行网络通讯
3、从库配置
3.1 修改从库配置文件
#1、修改配置文件
[root@rep1 ~]# vim /etc/my.cnf
[mysqld]
datadir=/data/mysql
socket=/data/mysql/mysql.sock
log_timestamps=SYSTEM
server_id=139
disabled_storage_engines="MyISAM,BLACKHOLE,FEDERATED,ARCHIVE,MEMORY"
gtid_mode=ON
enforce_gtid_consistency=ON
log_bin=binlog
log_slave_updates=ON
binlog_format=ROW
transaction_write_set_extraction=XXHASH64
plugin_load_add='group_replication.so'
group_replication_group_name="aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa"
group_replication_start_on_boot=off
group_replication_local_address= "192.168.83.139:33061"
group_replication_group_seeds= "192.168.83.138:33061,192.168.83.139:33061,192.168.83.140:33061"
group_replication_bootstrap_group=off
group_replication_ip_whitelist="192.168.83.0/24,127.0.0.1/8"
group_replication_recovery_use_ssl=on
[root@rep1 ~]# /etc/init.d/mysqld restart[root@rep2 ~]# vim /etc/my.cnf
[mysqld]
datadir=/data/mysql
socket=/data/mysql/mysql.sock
log_timestamps=SYSTEM
server_id=140
disabled_storage_engines="MyISAM,BLACKHOLE,FEDERATED,ARCHIVE,MEMORY"
gtid_mode=ON
enforce_gtid_consistency=ON
log_bin=binlog
log_slave_updates=ON
binlog_format=ROW
transaction_write_set_extraction=XXHASH64
plugin_load_add='group_replication.so'
group_replication_group_name="aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa"
group_replication_start_on_boot=off
group_replication_local_address= "192.168.83.140:33061"
group_replication_group_seeds= "192.168.83.138:33061,192.168.83.139:33061,192.168.83.140:33061"
group_replication_bootstrap_group=off
group_replication_ip_whitelist="192.168.83.0/24,127.0.0.1/8"
group_replication_recovery_use_ssl=on
#在所有从的数据库中添加复制账号并授予权限
SET SQL_LOG_BIN=0;
CREATE USER rp@'%' IDENTIFIED BY '123';
GRANT REPLICATION SLAVE ON *.* TO rp@'%';
GRANT CONNECTION_ADMIN ON *.* TO rp@'%';
GRANT BACKUP_ADMIN ON *.* TO rp@'%';
GRANT GROUP_REPLICATION_STREAM ON *.* TO rp@'%';
FLUSH PRIVILEGES;
SET SQL_LOG_BIN=1;
CHANGE REPLICATION SOURCE TO SOURCE_USER='rp', SOURCE_PASSWORD='123' FOR CHANNEL 'group_replication_recovery';
3.2 在所有从的数据库中添加复制账号并授予权限
#1、在所有从的数据库中添加复制账号并授予权限
SET SQL_LOG_BIN=0;
CREATE USER rp@'%' IDENTIFIED BY '123';
GRANT REPLICATION SLAVE ON *.* TO rp@'%';
GRANT CONNECTION_ADMIN ON *.* TO rp@'%';
GRANT BACKUP_ADMIN ON *.* TO rp@'%';
GRANT GROUP_REPLICATION_STREAM ON *.* TO rp@'%';
FLUSH PRIVILEGES;
SET SQL_LOG_BIN=1;
CHANGE REPLICATION SOURCE TO SOURCE_USER='rp', SOURCE_PASSWORD='123' FOR CHANNEL 'group_replication_recovery';#2、两个从库开启组复制
mysql> START GROUP_REPLICATION USER='rp', PASSWORD='123';#3、查看组信息
mysql> SELECT * FROM performance_schema.replication_group_members;`
4、验证结果
# 在主库节点数据库上执行
mysql> create database test;
mysql> use test
# 必须设置主键,不然无法插入数据
mysql> create table student(id int primary key,name char(30),age int,sex char(10));
mysql> insert into student values (1,'xiaoming',13,'男'),(2,'songxiao',18,'男'),(3,'dongyingying',22,'女');# 在三个节点均可以查看到新增信息
mysql> select * from test.student;
+----+--------------+------+------+
| id | name | age | sex |
+----+--------------+------+------+
| 1 | xiaoming | 13 | 男 |
| 2 | songxiao | 18 | 男 |
| 3 | dongyingying | 22 | 女 |
+----+--------------+------+------+
# 在从节点测试写入,验证不支持写入操作
mysql> insert into test.t1 values (4,'zhangzhuoyue',1,'男');
ERROR 1290 (HY000): The MySQL server is running with the --super-read-only option so it cannot execute this statement
# 测试主节点宕机
mysql> stop GROUP_REPLICATION;
# 从库节点查看,发现仅剩2个节点,并且自动选举出主节点
mysql> SELECT * FROM performance_schema.replication_group_members;
# 在重新选举出来的rep2上测试插入数据
mysql> insert into test.student values (4,'zhangzhuoyue',1,'男');mysql> mysql> select * from test.student;
+----+--------------+------+------+
| id | name | age | sex |
+----+--------------+------+------+
| 1 | xiaoming | 13 | 男 |
| 2 | songxiao | 18 | 男 |
| 3 | dongyingying | 22 | 女 |
| 4 | zhangzhuoyue | 1 | 男 |
+----+--------------+------+------+# 重新启动前面的master主节点,可以看到master已经作为从节点加入到群组中
mysql> START GROUP_REPLICATION;mysql> SELECT * FROM performance_schema.replication_group_members;
五、实现mysql组复制-多主模式
1、基本配置
# 修改所有的/etc/my.cnf的配置文件
[root@master ~]# vim /etc/my.cnf
# 关闭单master模式
loose-group_replication_single_primary_mode=off
# 多主一致性检查
loose-group_replication_enforce_update_everywhere_checks=ON[root@master ~]# /etc/init.d/mysqld restart
# 在其中一台主机里面执行以下命令
SET GLOBAL group_replication_bootstrap_group=ON;
START GROUP_REPLICATION;
SET GLOBAL group_replication_bootstrap_group=OFF;
# 在另外两台主机里,开启组复制
mysql> START GROUP_REPLICATION;
mysql> SELECT * FROM performance_schema.replication_group_members;
2、验证结果
# 在三个主机上面分别执行以下三条命令测试是否都可以执行写入操作
mysql> insert test.student values (5,'zhangjin',12,'男');
mysql> insert test.student values (6,'liuliang',8,'男');
mysql> insert test.student values (7,'hanzhuoya',2,'女');
mysql> select * from test.student;
+----+--------------+------+------+
| id | name | age | sex |
+----+--------------+------+------+
| 1 | xiaoming | 13 | 男 |
| 2 | songxiao | 18 | 男 |
| 3 | dongyingying | 22 | 女 |
| 4 | zhangzhuoyue | 1 | 男 |
| 5 | zhangjin | 12 | 男 |
| 6 | liuliang | 8 | 男 |
| 7 | hanzhuoya | 2 | 女 |
+----+--------------+------+------+