实战篇:MySQL高可用--MGR实战

Posted 进击的CJR

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了实战篇:MySQL高可用--MGR实战相关的知识,希望对你有一定的参考价值。

MGR特点

(1)基于Paxos协议和原生复制,多数节点同意即可通过事务提交
(2)具备高可用自动故障检测,可自动切换
(3)可弹性扩展,集群自动的新增和移除节点
(4)有单主和多主模式
(5)支持多节点写入,具备冲突检测机制,可以适应多种应用场景需求


MGR组复制是什么

(1)主从复制是异步复制

master事务的提交不需要经过slave的确认,slave是否接收到master的binlog,master并不care。slave接收到master binlog后先写relay log,最后异步地去执行relay log中的sql应用到自身。由于master的提交不需要确保slave relay log是否被正确接受,当slave接受master binlog失败或者relay log应用失败,master无法感知。

实战篇:MySQL高可用--MGR实战_mgr

(2)半同步复制

基于传统异步存在的缺陷,mysql在5.5版本推出半同步复制。可以说半同步复制是传统异步复制的改进,在master事务的commit之前,必须确保一个slave收到relay log并且响应给master后(从库收到并产生 relaylog 后会向主库发送一个 ACK 的信息包,当主库获得这个包后,认为从库已经获得 relaylog)才能进行事务的commit。但是slave对于relay log的应用仍然是异步进行的。

实战篇:MySQL高可用--MGR实战_实战mysql_02

(3)组复制

基于传统异步复制和半同步复制的缺陷——数据的一致性问题无法保证,MySQL官方在5.7.17版本正式推出组复制(MySQL Group Replication,简称MGR)。
由若干个节点共同组成一个复制组,一个事务的提交,必须经过组内大多数节点(N / 2 + 1)决议并通过,才能得以提交。如上图所示,由3个节点组成一个复制组,Consensus层为一致性协议层,在事务提交过程中,发生组间通讯,由2个节点决议(certify)通过这个事务,事务才能够最终得以提交并响应。
引入组复制,主要是为了解决传统异步复制和半同步复制可能产生数据不一致的问题。组复制依靠分布式一致性协议(Paxos协议的变体),实现了分布式下数据的最终一致性,提供了真正的数据高可用方案(是否真正高可用还有待商榷)。其提供的多写方案,给我们实现多活方案带来了希望。

实战篇:MySQL高可用--MGR实战_实战mysql_03

组复制脱离了传统的主从模式结构,是一个具有容错功能的集群架构,在组复制的架构中,有多个 server成员构成,并且每个成员都可以独立执行事务,也就意味着多写的功能,但是所有的读写事务必须在冲突校验完成后才能提交,如果是只读型的事务那么会直接提交。当某个节点上发出一个读写的事务准备提交时,那么这个节点就会向整个集群开始广播这次读写的变更和对应的一个校验标识符,然后会针对这个事务产生一个全局的顺序号,由于是有顺序号的,所以集群中的每个成员都会按照顺序去执行事务的变更从而保证了数据的一致性。
如果在不同的 server 上执行了相同的操作,并且产生了事务冲突,那么校验机制就会做成相应的判断,通常先提交的事务先执行,后提交的回滚。所以从某种程度上来说,组复制是一种伪同步复制模式。


组复制的模式


(1)单主模式

在单主模式下,组有一个设置为读写模式的单主 server。 组中的所有其他成员被自动设置为只读模式(超级只读模式)。主服务器通常是用于引导组的第一个 server,所有其他加入的 server 自动从主服务器同步并设置为只读。

实战篇:MySQL高可用--MGR实战_mysql_04

在单主机模式下,将禁用在多主机模式下部署的某些检查,因为系统会强制在组中每次只有一个写入server。 例如,在单主模式下允许对具有外键的表进行更改,而在多主模式下不允许。 在主服务器故障时,自动选主机制选择下一个主服务器。 通过按字典顺序(使用其 UUID)来排序剩余的 server 成员并选择列表中的第一个成员来作为下一个主服务器。
如果主服务器从组中移除,则启动主节点选择程序,然后从组中的其余 server 成员中选择新的主节点。通过查看新视图,按照词典顺序将 server 的 UUID 进行排序并选择第一个作为主节点。选择了新的主节点后,它将自动设置为只读,其他辅助节点仍然为辅助节点,因此也是只读。


(2)多主模式

多主模式,也就是所有节点都可以写入,每个节点基本都一样

实战篇:MySQL高可用--MGR实战_实战mysql_05

PXC和MGR的区别

(1)执行提交PXC 事务需要在所有节点跑一下
MGR 多数节点同意,即可执行
(2)复制
PXC 在复制上需要Gcache中缓存
MGR 直接写binlog
(3)新增节点
新增节点PXC支持mysqldump xtrabackup
MGR直接集成复制克隆
(4)网络中断
网络中断发生时,PXC具有分区的表不可读写
MGR 可读不可写

(5)流控
MGR 写入变慢
PXC所有节点不可写
(6)跨平台
跨平台;PXC支持Linux
MGR支持所有平台(7)DDL当PXC在进行DDL时,为了保证节点数据一致,此时整个集群拒绝写操作,注意是集群内所有的表写操作均无法提供写服务,但是读操作可以正常进行。MGR 采用innodb存储引擎,支持在线DDL

单主多主模式搭建

单主搭建(5.7)

规划主机
我这里用三台虚拟机
192.168.168.101 3306
192.168.168.102 3306
192.168.168.103 3306

(1)配置host和IP的映射
在三台主机上分别 vi /etc/hosts
mysql 的组复制依然存在解析 host 的 bug,所以我们必须在所有节点内把 host和 ip 的映射关系配置完毕。
192.168.168.101 master1
192.168.168.102 slave2
192.168.168.103 slave3

实战篇:MySQL高可用--MGR实战_mgr_06

(2)关闭防火墙
查看centos7的防火墙
firewall-cmd --state

停止firewall
systemctl stop firewalld.service

禁止firewall开机启动
systemctl disable firewalld.service

实战篇:MySQL高可用--MGR实战_高可用_07

(3)快速初始化3台mysql库
1、压缩包解压
tar -xvf mysql-5.7.21-linux-glibc2.12-x86_64.tar.gz
mv mysql-5.7.21-linux-glibc2.12-x86_64.tar.gz /usr/local/mysql

2、配置环境变量
vi /etc/profile
export PATH=/usr/local/mysql/bin:$PATH
source /etc/profile

3、编辑mysql配置文件
vi /etc/my.cnf
[mysqld]
user=mysql
basedir=/usr/local/mysql
datadir=/data/3306/data
log_bin=/data/3306/binlog/mysql-bin
port=3306
server_id=1013306 #(另外两台机器 server_id=1023306\\ server_id=1033306)
socket=/tmp/mysql.sock
gtid-mode=on
enforce-gtid-consistency=true
log_slave_updates=1
relay_log_info_repository=TABLE
master_info_repository=TABLE
relay_log_recovery=on

4、创建数据目录和赋权
mkdir -p /data/3306/data
mkdir -p /data/3306/binlog
chown mysql:mysql -R /data


5、初始化
mysqld --defaults-file=/etc/my.cnf --basedir=/usr/local/mysql --initialize-insecure --datadir=/data/3306/data --user=mysql &

6、启动
mysqld_safe --defaults-file=/etc/my.cnf --user=mysql &

7、登录
mysql -u root
mysql -S /tmp/mysql3306.sock -u root

(4)配置mgr参数
分别在三台配置文件my.cnf上添加,配置后重启生效
101上:transaction_write_set_extraction=XXHASH64
loose-group_replication_group_name ="a876d35e-9110-11e6-a365-842b2b5909d6"
loose-group_replication_start_on_boot =off
loose-group_replication_local_address ="192.168.168.101:34901"
loose-group_replication_group_seeds ="192.168.168.101:34901,192.168.168.102:34902,192.168.168.103:34903"
loose-group_replication_bootstrap_group =off
loose-group-replication-ip-whitelist="192.168.168.101,192.168.168.102,192.168.168.103"

102上:
transaction_write_set_extraction=XXHASH64
loose-group_replication_group_name ="a876d35e-9110-11e6-a365-842b2b5909d6"
loose-group_replication_start_on_boot =off
loose-group_replication_local_address ="192.168.168.102:34902"
loose-group_replication_group_seeds ="192.168.168.101:34901,192.168.168.102:34902,192.168.168.103:34903"
loose-group_replication_bootstrap_group =off
loose-group-replication-ip-whitelist="192.168.168.101,192.168.168.102,192.168.168.103"

103上:
transaction_write_set_extraction=XXHASH64
loose-group_replication_group_name ="a876d35e-9110-11e6-a365-842b2b5909d6"
loose-group_replication_start_on_boot =off
loose-group_replication_local_address ="192.168.168.103:34903"
loose-group_replication_group_seeds ="192.168.168.101:34901,192.168.168.102:34902,192.168.168.103:34903"
loose-group_replication_bootstrap_group =off
loose-group-replication-ip-whitelist="192.168.168.101,192.168.168.102,192.168.168.103"

分别将三台库重启
mysqld\\_safe --defaults-file=/etc/my.cnf --user=mysql &

实战篇:MySQL高可用--MGR实战_mgr_08

(5)创建组复制用户
SET SQL\\_LOG\\_BIN=0;
CREATE USER repl@% IDENTIFIED BY repl;
GRANT REPLICATION SLAVE ON \\*.\\* TO repl@%;
FLUSH PRIVILEGES;
SET SQL\\_LOG\\_BIN=1;

(6)安装组复制插件
在3套库上都安装
INSTALL PLUGIN group\\_replication SONAME group\\_replication.so;
show plugins;

实战篇:MySQL高可用--MGR实战_实战mysql_09

(7)启动并引导组复制
在单主模式中我们需要默认的选择一个节点作为主节点,并且使这个节点成为引导节点。
选择在101主机上的 mysql 中运行以下的命令
SET GLOBAL group_replication_bootstrap_group=ON;
START GROUP_REPLICATION;
SET GLOBAL group_replication_bootstrap_group=OFF;
SET GLOBAL group\\_replication\\_bootstrap\\_group=ON; 意思是打开节点的引导模式
START GROUP\\_REPLICATION; 意思是开启同步
SET GLOBAL group\\_replication\\_bootstrap\\_group=OFF; 在我们将节点一设置为引导节点后关闭

实战篇:MySQL高可用--MGR实战_mgr_10

启动报错,查看日志

实战篇:MySQL高可用--MGR实战_高可用_11

set @@global.binlog\\_checksum=none;
在3套库上都需要执行,可以写入配置文件

实战篇:MySQL高可用--MGR实战_mgr_12

可以查看到,改节点已经加入到集群中 ONLINE

实战篇:MySQL高可用--MGR实战_实战mysql_13

在erro日志中看到到节点 1 已经通过 MGR 的内部通信管理 GCS 加入到节点中

实战篇:MySQL高可用--MGR实战_高可用_14

查看是否是主节点,可以看到101主机的库是主节点
​select * from performance_schema.replication_group_members;查询节点是否正常​

8.0版本可以直接通过表performance\\_schemaerformance\\_schema.replication\\_group\\_members查看是否是主节点,在5.7中查看是否主节点需要这样查
​SELECT IF((SELECT @@server_uuid) = (SELECT VARIABLE_VALUE FROM performance_schema.global_status WHERE VARIABLE_NAME= group_replication_primary_member), 1, 0) as is_primary_node;​

实战篇:MySQL高可用--MGR实战_mysql_15

测试:
为了验证组复制是否能做到加入的节点后自动同步,我们这里可以在节点 1 上造一点数据
这里我创建了一些库和一些表。等节点 2 和节点 3 加入组后观察是否同步
`​​create database test; use test; create table t(id int,name varchar(30),PRIMARY KEY (​​id​​)); insert into t select 1,aa;​​`

实战篇:MySQL高可用--MGR实战_mysql_16

(8)节点2加入
set @@global.binlog_checksum=none;CHANGE MASTER TO MASTER_USER=repl, MASTER_PASSWORD=repl FOR CHANNEL group_replication_recovery;
START GROUP_REPLICATION;
2节点加入到集群,且不是主

实战篇:MySQL高可用--MGR实战_mysql_17

如果是8.0的MGR,可以直接从这里查到是否是主

实战篇:MySQL高可用--MGR实战_mysql_18

数据也自动同步过来了,验证了组复制新加入的节点数据自动同步

实战篇:MySQL高可用--MGR实战_mgr_19

(9)节点3加入
set @@global.binlog_checksum=none;CHANGE MASTER TO MASTER_USER=repl, MASTER_PASSWORD=repl FOR CHANNEL group_replication_recovery;
START GROUP_REPLICATION;
3节点加入集群,且不是主

实战篇:MySQL高可用--MGR实战_高可用_20

可以查看,数据已经同步过来了,再次验证了组复制新加入的节点数据自动同步

实战篇:MySQL高可用--MGR实战_mysql_21

注意:配置文件没有写
`loose-group_replication_single_primary_mode = true
loose-group_replication_enforce_update_everywhere_checks = false`
在5.7中,开始组复制之前,可以手动配置写入
set global group_replication_single_primary_mode=true;
set global group_replication_enforce_update_everywhere_checks = false;
当然如果不写,默认是

实战篇:MySQL高可用--MGR实战_实战mysql_22

多主搭建


多主节点搭建基本和单主步骤一样,只需要配置文件my.cnf额外添加,本文以下示例为单主节点搭建,多主节点搭建亦相差无几
loose-group\\_replication\\_single\\_primary\\_mode=FALSE
loose-group\\_replication\\_enforce\\_update\\_everywhere\\_checks= TRUE


单主搭建(8.0)

1、压缩包解压
tar -xvf mysql-8.0.25-linux-glibc2.12-x86_64.tar
rm -rf /usr/local/mysql
mv mysql-8.0.25-linux-glibc2.12-x86_64 /usr/local/mysql

2、配置环境变量
vi /etc/profile
export PATH=/usr/local/mysql/bin:$PATH
source /etc/profile


3、编辑mysql配置文件
vi /etc/my.cnf
[mysqld]
user=mysql
basedir=/usr/local/mysql
datadir=/data/3306/data
log_bin=/data/3306/binlog/mysql-bin
port=3306
server_id=1013306 #(另外两台机器 server_id=1023306\\ server_id=1033306)
socket=/tmp/mysql.sock
gtid-mode=on
enforce-gtid-consistency=true
log_slave_updates=1
relay_log_info_repository=TABLE
master_info_repository=TABLE
relay_log_recovery=on

--101----------------------------------------------------------------------------------------------------------
transaction_write_set_extraction=XXHASH64
loose-group_replication_group_name ="a876d35e-9110-11e6-a365-842b2b5909d6"
loose-group_replication_start_on_boot =off
loose-group_replication_local_address ="192.168.168.101:34901"
loose-group_replication_group_seeds ="192.168.168.101:34901,192.168.168.102:34902,192.168.168.103:34903"
loose-group_replication_bootstrap_group =off
loose-group-replication-ip-whitelist="192.168.168.101,192.168.168.102,192.168.168.103"

--102----------------------------------------------------------------------------------------------------------
transaction_write_set_extraction=XXHASH64
loose-group_replication_group_name ="a876d35e-9110-11e6-a365-842b2b5909d6"
loose-group_replication_start_on_boot =off
loose-group_replication_local_address ="192.168.168.102:34902"
loose-group_replication_group_seeds ="192.168.168.101:34901,192.168.168.102:34902,192.168.168.103:34903"
loose-group_replication_bootstrap_group =off
loose-group-replication-ip-whitelist="192.168.168.101,192.168.168.102,192.168.168.103"


--103----------------------------------------------------------------------------------------------------------
transaction_write_set_extraction=XXHASH64
loose-group_replication_group_name ="a876d35e-9110-11e6-a365-842b2b5909d6"
loose-group_replication_start_on_boot =off
loose-group_replication_local_address ="192.168.168.103:34903"
loose-group_replication_group_seeds ="192.168.168.101:34901,192.168.168.102:34902,192.168.168.103:34903"
loose-group_replication_bootstrap_group =off
loose-group-replication-ip-whitelist="192.168.168.101,192.168.168.102,192.168.168.103"

------------------------------------------------------------------------------------------------------------

4、创建数据目录和赋权
mkdir -p /data/3306/data
mkdir -p /data/3306/binlog
chown mysql:mysql -R /data


5、初始化

mysqld --defaults-file=/etc/my.cnf --basedir=/usr/local/mysql --initialize-insecure --datadir=/data/3306/data --user=mysql &

6、启动
mysqld_safe --defaults-file=/etc/my.cnf --user=mysql &

7、登录
mysql -u root
mysql -S /tmp/mysql3306.sock -u root
8、安装组复制插件
INSTALL PLUGIN group_replication SONAME group_replication.so;
show plugins;9、在101上创建复制用户SET SQL_LOG_BIN=0;CREATE USER repl@% IDENTIFIED WITH mysql_native_password BY repl;
GRANT REPLICATION SLAVE ON *.* TO repl@%;
GRANT BACKUP_ADMIN ON *.* TO repl@%;
FLUSH PRIVILEGES;
SET SQL_LOG_BIN=1;
10、启动并引导组复制
在单主模式中我们需要默认的选择一个节点作为主节点,并且使这个节点成为引导节点。
在 mysql 中运行以下的命令
SET GLOBAL group_replication_bootstrap_group=ON;
START GROUP_REPLICATION;
SET GLOBAL group_replication_bootstrap_group=OFF;11、依次在另外两个节点CHANGE MASTER TO MASTER_USER=repl, MASTER_PASSWORD=repl FOR CHANNEL group_replication_recovery;
START GROUP_REPLICATION;

如下为8.0的单主三节点MGR集群

实战篇:MySQL高可用--MGR实战_高可用_23


组复制监控常用相关表

MGR单个节点状态

实战篇:MySQL高可用--MGR实战_mgr_24

MGR整个组的状态

实战篇:MySQL高可用--MGR实战_mgr_25

主要用到4张表

performance_schema.replication_group_member_stats

performance_schema.replication_group_members

performance_schema.replication_connection_status

performance_schema.replication_applier_status


1. replication_group_member_stats

是用来展示组复制所有成员信息的表,有关验证和应用程序的统计信息对于了解申请队列增长情况、触发了多少冲突、检查了多少事务、哪些事务已被所有成员提交等等非常有用。

这张表主要是监控各个节点的性能,如果出现某个节点的事务号和其他节点差很多,那这个节点肯定出现了延迟,如果长时间的延迟,极有可能被群员投票给踢出去。

这张表只有在配置组复制后才会有数据。其中字段包括。

实战篇:MySQL高可用--MGR实战_实战mysql_26


其中最重要的列,也是经常被观察的指数如下

COUNT_TRANSACTTIONS_IN_QUEUE:组复制队列中等待冲突检测的事务数,只有当冲突检测通过才会排队应用到各个节点上(远程等待被确认的事务数)

COUNT_TRANSACTIONS_REMOTE_IN_APPLIER_QUEUE:当前节点收到的等待的事务数(远程的事务还有多少没有被应用)

COUNT_TRANSANCTIONS_CHECKED:已经通过冲突检测的事务数

COUNT_TRANSACTIONS_REMOTE_APPLIED:当前节点收到的应用的事务数(本地已经应用的事务数)

COUNT_TRANSACTIONS_LOCAL_PROPOSED:源自此成员并发送给复制组的事务数。(本地已经提交的事务数)

----------------------------------------------------------------------------------------------------------------------------

CANNEL_NAME:这个组复制通道的名称

VIEW_ID:组复制对应的视图号

MEMBER_ID:复制中组成员的 ID,这个 ID 和本身 mysql 实例的 UUID 没关系

COUNT_CONFLICTS_DETECTED:未通过冲突检测的事务数

COUNT_TRANSACTIONS_ROWS_VALIDATING:冲突检查数据库的大小

TRANSACTIONS_COMMITTED_ALL_MEMBERS:已在复制组的所有成员上成功提交的事务,显示为 GTID 集。

LAST_CONFLICT_FREE_TRANSACTION:最后一次冲突事务的 GITD 号

COUNT_TRANSACTIONS_REMOTE_APPLIED:当前节点收到的应用的事务数

COUNT_TRANSACTIONS_LOCAL_PROPOSED:源自此成员并发送给复制组的事务数。

COUNT_TRANSACTIONS_LOCAL_ROLLBACK:源自此成员并被复制组回滚的事务数。




2.replication_group_members

用于监控组内成员复制状态的表

实战篇:MySQL高可用--MGR实战_mysql_27

CHANNEL_NAME:组复制的通道名

MEMBER_ID:组成员 ID

MEMBER_HOST:组成员的主机名

MEMBER_PORT:组成员数据库实例端口,注意这里是实例端口

MEMBER_STATE:组成员当前的状态,这个栏位总共有 4 个状态Online 表示正常工作状态,表示该节点目前一切 OK。

Recovering 表示节点正在加入组中,这个状态有可能是正在同步数据,也有可能是正在和主节点发生通信,如果长期处于这个状态,往往是 host 没配,需要检查下 host 配置
Offline 表示这个节点的组复制插件已经加载
Unreachable 表示经过仲裁,某个节点已经崩溃或者不可访问。

MEMBER_ROLE:成员在组内的角色,如果是单主模式,主的节点就会显示 PRIMARY,其他节点显示 SECONDARY,如果是多主模式,所有节点均为 PRIMARY。

MEMBER_VERSION:mysql 的版本


3. replication_connection_status

用于记录当前节点连接状态的表

实战篇:MySQL高可用--MGR实战_mysql_28

CHANNEL_NAME:组复制通道名。

GROUP_NAME:组复制名,就是组的 UUID 号。

SOURCE_UUID:组复制源的 UUID 号。

THREAD_ID:组复制 I/O 功能的 threadid

SERVICE_STATE:显示成员当前的活跃状态,

COUNT_RECEIVED_HEARTBEATS:从上一次重置主从后获得的心跳数

LAST_HEARTBEAT_TIMESTAMP:节点的最后一次心跳时间

RECEIVED_TRANSACTION_SET:与该从站接收的所有事务相对应的一组全局事务 ID(GTID)。如果未使用 GTID,则为空。

LAST_ERROR_NUMBER:最后一次 I/O 同步线程错误编号,0 为无错误

LAST_ERROR_MESSAGE:最后一次 I/O 同步线程错误日志,记录在 mysql 错误日志中

LAST_ERROR_TIMESTAMP:最后一次 I/O 线程错误的时间。

LAST_QUEUED_TRANSACTION:该节点同步的 relay log 中最后一个事务的 GTID 号

LAST_QUEUED_TRANSACTION_ORIGINAL_COMMIT_TIMESTAMP:最后一次,在各个节点中写入的事务准备好提交,产生写集并且发送到各个节点做冲突校验时候的时间。

LAST_QUEUED_TRANSACTION_IMMEDIATE_COMMIT_TIMESTAMP:最后一次事务最终提交的时间。LAST_QUEUED_TRANSACTION_START_QUEUE_TIMESTAMP:I / O 线程将最后一个事务放置在 relaylog 中的时间

LAST_QUEUED_TRANSACTION_END_QUEUE_TIMESTAMP:进入 relaylog 排队的时间

QUEUEING_TRANSACTION:当前 relaylog 中全局事务的 ID

QUEUEING_TRANSACTION_ORIGINAL_COMMIT_TIMESTAMP:当前事务进入写集的时间

QUEUEING_TRANSACTION_IMMEDIATE_COMMIT_TIMESTAMP:当前事务最后提交的时间

QUEUEING_TRANSACTION_START_QUEUE_TIMESTAMP:当前日志进入 relaylog 的时间


可用此表来判断延迟

select RECEIVED_TRANSACTION_SET from replication_connection_status where CHANNEL_NAME=group_replication_applier
union all
select VARIABLE_VALUE from global_variables where VARIABLE_NAME =gtid_executed;

本地已经执行的GTID和接收到远程的GTID的差异

实战篇:MySQL高可用--MGR实战_实战mysql_29



4. replication_applier_status

用于显示当前组复制线程干了啥的表

实战篇:MySQL高可用--MGR实战_实战mysql_30

CHANNEL_NAME:复制通道的名字

SERVICE_STATE:当复制通道的应用程序线程处于活动或空闲状态时显示为 ON,表示关闭时,应用程序线程未处于活动状态

REMAINING_DELAY:同步复制线程的延迟时间。

COUNT_TRANSACTIONS_RETRIES:SQL 线程无法应用日志重试的次数


单主多主模式切换

实验演示规划

(3台虚拟机。MySQL版本8.0.25)

192.168.168.101 master1(简称1节点)

192.168.168.102 slave2   (简称2节点)

192.168.168.103 slave3   (简称3节点)


在 MGR 中,单主模式是只有一个主节点可以写,其余均为只读节点,且只读节点的 super read only 为打开状态,即使 root 用户依然无法写。多主模式则为全节点均可写。


单主切多主

MGR 单切多使用的命令为select group_replication_switch_to_multi_primary_mode();

首先我们观察当前集群的模式和各个节点的读写模式

select * from performance_schema.replication_group_members;

show variables like %read_only%;


1节点


实战篇:MySQL高可用--MGR实战_mgr_31

2节点

实战篇:MySQL高可用--MGR实战_高可用_32

3节点

实战篇:MySQL高可用--MGR实战_mysql_33


可以看到,各个节点的读写模式是符合单主模式的。接下来我们在任意节点执行切换语句,此处我们在节点 1 上执行。

select group_replication_switch_to_multi_primary_mode();

实战篇:MySQL高可用--MGR实战_实战mysql_34

可以看到节点 1 因为一开始就是主节点,所以读写模式没有发生变化,但是节点 2 和节点 3 已经自动关闭了只读模式,所有节点都变成可写。

实战篇:MySQL高可用--MGR实战_mgr_35


多主切单主

MRG 多主切单主有两条命令可以使用

不指定主节点进行切换

select group_replication_switch_to_single_primary_mode();

MGR 中多主切单主,如果不指定主,切换时遵循以下的规则,前提无延迟情况下,按照优先级先后顺序:

1、 先检查集群内是否存在低版本的 mysql,如果所有成员都是 8.0.17 版本以上的,则按照补丁先后顺序排列,如果有成员是 8.0.17 版本以下的,或者 5.7 的按发行版本的主要版本来排序,忽略补丁编号。

2、 如果集群有任意一个低版本的 mysql。且支持 group_replication_member_weight 这个参数的版本的mysql。则根据 group_replication_member_weight 这个权重参数来,group_replication_member_weight

默认都是 50,权重越高优先级越高。

3、 如果集群内有不支持 group_replication_member_weight 参数的 mysql,比如有 mysql5.7 的,并且其中一个以上的成员具有最高的成员权重(或忽略了成员权重),则考虑的第三个因素是生成的服务器 UUID 的词典顺序,由 server_uuid 系统变量指定。服务器 UUID 最低的成员被选为主服务器,这里实际上就是查询 performance_schema.replication_group_members 最靠前的且是活着的MEMBER_ID。

在节点 1 上执行非指定单主的切换 SQL

实战篇:MySQL高可用--MGR实战_高可用_36

可以看到选取了 server_uuid 靠前的节点 1成为主节点。

接下来我们观察各个节点的读写情况

1节点

实战篇:MySQL高可用--MGR实战_高可用_37

2节点

实战篇:MySQL高可用--MGR实战_mgr_38

3节点

实战篇:MySQL高可用--MGR实战_mysql_39

可以看到此时节点 1 作为主节点已经关闭了 read only,其他节点都已经打开了只读。


指定单主切换

因为随机切有很大的不确定性,这里还提供了指定主节点的切换命令

select group_replication_set_as_primary("member_id");

这里的 member_id 就是 server_uuid我们在节点 1 执行切换命令,选择2节点的member_id。

切换后,可以看到节点1打开了只读变成了从节点

实战篇:MySQL高可用--MGR实战_实战mysql_40

节点2,关闭了只读,成为主节点

实战篇:MySQL高可用--MGR实战_高可用_41

节点3,不变

实战篇:MySQL高可用--MGR实战_实战mysql_42


异常恢复

网络异常​​

MGR 对网络要求很高,有的时候会因网络波动,自动退出集群的情况,此时需要先在出问题的节点停止组复制,然后再重新加入到集群中。

如下,该节点被踢出集群,直接执行Stop group_replication;报错

实战篇:MySQL高可用--MGR实战_高可用_43

需要先执行 stop group_replication 然后再 start group_replication

Stop group_replication;

Start group_replication;

实战篇:MySQL高可用--MGR实战_mysql_44


节点启动长时间处于RECOVERING

实战篇:MySQL高可用--MGR实战_mysql_45

查看日志

实战篇:MySQL高可用--MGR实战_mgr_46

在主节点将密码的加密方式修改

SET SQL_LOG_BIN=0;

alter USER repl@% IDENTIFIED WITH mysql_native_password BY repl;

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

GRANT BACKUP_ADMIN ON *.* TO repl@%;

FLUSH PRIVILEGES;

SET SQL_LOG_BIN=1;

在重启两个从节点

STOP GROUP_REPLICATION;

START GROUP_REPLICATION;

2节点状态恢复正常

实战篇:MySQL高可用--MGR实战_mgr_47

3节点状态恢复正常

实战篇:MySQL高可用--MGR实战_mysql_48


数据异常修复

暂时性恢复

MGR 对数据具有一定的容错性和最终一致性,原则上并不会出现数据不一致的情况,并且每次执行事务都会检测冲突,然后如果当某个节点的数据因为异常导致不一致,切主节点的 binlog 丢失的情况,势必会导致集群数据不一致,此时可以通过以下的方法暂时让集群起来。


停止异常节点的组复制
Stop group_replication;

清空当前的 GTID EXECUTED
Reset master;

在异常节点将 GTID 事务号设置和主节点一致
SET @@GLOBAL.GTID_PURGED=主节点的 GTID 号;

启动异常节点的组复制
Start group_replication;

这里需要注意,这样的方式即使恢复了集群,因为 binlog 的缺失,实际上数据是不一致的,极有可能发生后续因为数据不一致导致集群出现问题,这里强烈不建议这么做。


分布式恢复

前面提到了暂时性的集群恢复,这样的恢复会有很大的问题,这里说下 MGR 正常的恢复方式,MGR 当新的成员加入节点时,通常有两种方法,当 binlog 全,或者 binlog 在删除前接入的节点能够成功继续往下同

步的。则新加入的节点会继续同步下去,在 mysql8.0.21 版本中,可以通过设置参数

group_replication_advertise_recovery_endpoints 这个参数来进行指定的点进行同步。

如果当 binlog 不可用或者差的数据实在太多时,mysql 在 8.0.17 后退出了克隆的方式进行恢复,即在集群中的所有 mysql 节点上添加克隆插件,新加入的节点数据将会被全部删除,然后会被自动重新同步数据。


节点分布式恢复

读节点重新加入环境

模拟读节点重新加入,首先观察主节点的数据以及事务的情况

此时将节点 3,然后清除所有数据,清除同步信息,重新初始化 mysql,模拟成新节点

已有数据

实战篇:MySQL高可用--MGR实战_mgr_49

关库

实战篇:MySQL高可用--MGR实战_mgr_50

删数据文件

实战篇:MySQL高可用--MGR实战_mysql_51

此时3节点已经被集群踢出去了

实战篇:MySQL高可用--MGR实战_高可用_52

重新初始化,启动,并登录

初始化
mysqld --defaults-file=/etc/my.cnf --basedir=/usr/local/mysql --initialize-insecure --datadir=/data/3306/data --user=mysql &

启动
mysqld_safe --defaults-file=/etc/my.cnf --user=mysql &

登录
mysql -u root

实战篇:MySQL高可用--MGR实战_mgr_53

实战篇:MySQL高可用--MGR实战_mysql_54

这里注意,因为 2 节点的的 ip 已经添加到了所有节点的 group_replication_group_seeds 中,所以不再添加,如果是新的 ip 加入节点,必须在所有其他节点上 group_replication_group_seeds 中添加新节点的IP。

按照搭建 MGR 节点的步骤,将节点 2 添加到集群中


Reset master;

INSTALL PLUGIN group_replication SONAME group_replication.so;

CHANGE MASTER TO MASTER_USER=repl, MASTER_PASSWORD=repl FOR CHANNEL group_replication_recovery;

START GROUP_REPLICATION;

实战篇:MySQL高可用--MGR实战_mysql_55

已经重新加入到集群中,数据也同步回来

实战篇:MySQL高可用--MGR实战_实战mysql_56

实战篇:MySQL高可用--MGR实战_高可用_57

可以看到同步事务已经一致

实战篇:MySQL高可用--MGR实战_mysql_58


克隆恢复

Mysql8.0.17 后可以使用克隆恢复

这里我们依然采用节点 3 作为需要接收克隆的节点

首先在源节点和接收克隆的节点添加克隆插件

​INSTALL PLUGIN clone SONAME mysql_clone.so;​

同样因为是组复制,所以节点 3 必须装组复制插件

INSTALL PLUGIN group_replication SONAME group_replication.so;

实战篇:MySQL高可用--MGR实战_实战mysql_59


其次在提供克隆的节点上,也就是节点 1 上赋权


MySQL高性能高可用表设计实战-表设计篇(MySQL专栏启动)

云原生时代必须具备的核心技能之Docker高级篇(Docker实战之MySQL高可用集群搭建)

企业级Nginx负载均衡与keepalived高可用实战keepalived篇

技术实战:基于 MHA 方式实现 MySQL 的高可用(转)

高可用Hadoop平台-Flume NG实战图解篇

运维实战 Mysql高可用与健康检查