MGR初探

本文涉及的产品
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
云数据库 RDS MySQL,高可用系列 2核4GB
简介: MySQL Group Replication(MGR)是MySQL官方在5.7.17版本引进的一个数据库高可用与高扩展的解决方案,以插件形式提供。MGR基于分布式paxos协议,实现组复制,保证数据一致性。

一、MGR基础

1、复制背景
1.1 主从复制
传统MySQL提供了一种简单的主从复制方式,一个主,有一个或者多个从。主节点执行和提交事务,然后将他们发送到从节点,以重新执行(在基于语句的复制中)或者应用(在基于行的复制中)。这是一个 shared-nothing的系统,默认所有的server都有一个完整的数据副本。
test

MySQL异步复制


可以看到的是,异步复制是不考虑从库有没有接受binlog文件的,所以会造成主从不一致: 当主库commit一个事务后,数据库发生宕机,刚好它的binlog还没来得及传送到slave端,这个时候选任何一个slave端都会丢失这个事务,造成数据不一致情况。
所以还要一种半同步复制,它在协议中加了一个同步的步骤,这意味着主节点提交的时候需要等待从节点确认它已经收到了事物,只有这样主节点才能够继续提交。
test

MySQL半同步复制

从上面两个图中可以看到传统的MySQL复制协议。蓝色的箭头表示不同的server之间或者server和client应用之间的信息交互。

1.2 组复制
不管是异步复制还是半同步复制,都有两个弊端:

  • 写操作集中在MASTER服务器上;
  • MASTER宕机后,需要人为选择新主并重新给其他的slave端执行change master(可用第三方工具实现,但是mysql的复制就是没提供,所以也算是弊端)
    基于这种现状,MySQL官方提供了 MySQL Group Replication。

test

MySQL组复制

相对于传统的复制,MGR提供的功能有:
  • 多主:多写模式下支持集群中的所有节点都可以写入
  • 一致性: 依靠分布式一致性协议(Paxos协议的变体)确保集群中大部分节点收到日志
  • 弹性:同个MGR中,节点的加入或者移除都是自动调整
  • 可用性: 确保系统发生故障(包括脑裂)依然可用,双写对系统无影响

2、理论基础
MGR有单主和多主两种模式。
1.1 组复制
复制组由多个server成员组成,并且组中每个成员可以独立的执行事务。但是所有的读写(RW)事务只有在冲突检测成功后才会提交。只读事务(RO)不需要冲突检测,可以立即提交。
在始发server上,当事务准备好提交时,该server会广播写入值(已改变的行)和对应的写入集(已更新行的唯一标识符)。然后为该事物建立一个全局的顺序。最终,这意味着所有server成员以相同的顺序接收同一组事务。
因此,所有的server成员以相同的顺序应用相同的更改,以确保组内一致。
在不同的server上并发执行的事物可能存在冲突,根据组复制冲突检测机制。如果在不同server上执行的两个并发事务更新同一行,则存在冲突。冲突解决过程中,排在最前面的事物可以在所有server成员上提交,第二个事物在源server上回滚,并且在组中其他server上删除。其实这就是分布式的先提交当选原则。

1.2 容错
MySQL Group Replication构建于Paxos分布式算法的实现之上,以在服务器之间提供分布式协调。因此,它需要大多数服务器处于活动状态才能达到仲裁成员数,从而做出决定。这直接影响系统可以容忍的故障数量,以及自身及其整体功能。容忍f个故障所需的服务器数量 n= 2 x f + 1。
在实践中,这意味着为了容忍一个故障,该组必须具有三个server。因此,如果一个server发生故障,仍然有两个server构成多数(三分之二),并允许系统继续自动做出决策并继续进行。但是,如果第二个server以外fail掉 ,那么该组(剩下一个server)会锁定,因为没有多数人可以达成协议。
test

二、部署安装

1、单写部署
官方文档提供的是在一台服务器上安装3个mysql来搭建单主模式,这里是按照官方文档的步骤,但是部署在三台服务器上。
1.1 环境:
_
1.2 配置文件
编辑配置文件/data1/my3306.cnf,3个节点 除了server_id、loose-group_replication_local_address、report_host 三个参数不一样外,其他保持一致。

#GTID
server_id=11
gtid_mode=ON
#强制gtid一致性,开启后对于特定create table不被支持
#ON:不允许任何事务违反GTID一致性
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

#MGR
#定义用于生成标识与事务关联的写入的哈希的算法,哈希值将用于分布式冲突检测和处理
transaction_write_set_extraction=XXHASH64
#通知插件它正在加入或创建的组,可以使用SELECT UUID()生成一个UUID
loose-group_replication_group_name="aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa"
#指示插件在服务器启动时不自动引导组操作
loose-group_replication_start_on_boot=OFF
件使用哪个ip:port与组中的其他成员进行内部通信。这里的ip与端口不能与MySQL提供的ip:port 相同,如果使用相同ip则port必须不相同
loose-group_replication_local_address= "192.168.1.11:33061"
#设置组成员的主机名和端口
loose-group_replication_group_seeds= "192.168.1.11:33061,192.168.1.12:33061,192.168.1.13:33061"
#插件是否引导组,此选项只能在任何时候在一个服务器实例上使用,通常是第一次引导组时(或者在整个组关闭并重新备份的情况下)
loose-group_replication_bootstrap_group= off

1.3 安装启动
每个服务器是一个节点,都安装好mysql

mysqld --defaults-file=/data1/my3306.cnf --datadir=/data1/mysql3306 --user=mysql3306 --initialize-insecure
mysqld --defaults-file=/data1/my3308.cnf --datadir=/data1/mysql3308 --user=mysql3308 --initialize-insecure

启动:

/usr/local/mysql-5.7.26/bin/mysqld_safe --defaults-file=/data1/mysql3306/my3306.cnf &
/usr/local/mysql-5.7.26/bin/mysqld_safe --defaults-file=/data1/mysql3308/my3308.cnf &

1.4 安装MGR插件,设置复制账号(所有节点执行)

#无密码登录
#安装MGR插件
mysql> INSTALL PLUGIN group_replication SONAME 'group_replication.so';
#设置复制账号
mysql> SET SQL_LOG_BIN=0;
mysql> CREATE USER repl@'%' IDENTIFIED BY 'repl';
mysql> GRANT REPLICATION SLAVE ON *.* TO repl@'%';
mysql> FLUSH PRIVILEGES;
mysql> SET SQL_LOG_BIN=1;
mysql> CHANGE MASTER TO MASTER_USER='repl', MASTER_PASSWORD='repl' FOR CHANNEL 'group_replication_recovery';

1.5 启动MGR单主模式

#主启动(任选一个作为主库,这里选择了1.11)
SET GLOBAL group_replication_bootstrap_group=ON;
START GROUP_REPLICATION;
SET GLOBAL group_replication_bootstrap_group=OFF;
mysql> SELECT * FROM performance_schema.replication_group_members;
#查看MGR组信息
+---------------------------+--------------------------------------+-------------+-------------+--------------+
| CHANNEL_NAME              | MEMBER_ID                            | MEMBER_HOST | MEMBER_PORT | MEMBER_STATE |
+---------------------------+--------------------------------------+-------------+-------------+--------------+
| group_replication_applier | 463679cf-7222-11e9-9459-000c29a6154a | vm1         |        3306 | ONLINE       |
+---------------------------+--------------------------------------+-------------+-------------+--------------+

#其他节点加入MGR,在从库(1.12,1.13)上执行
mysql> START GROUP_REPLICATION;
mysql> SELECT * FROM performance_schema.replication_group_members;
+---------------------------+--------------------------------------+--------------+-------------+--------------+
| CHANNEL_NAME              | MEMBER_ID                            | MEMBER_HOST  | MEMBER_PORT | MEMBER_STATE |
+---------------------------+--------------------------------------+--------------+-------------+--------------+
| group_replication_applier | 0bbd0bcc-7223-11e9-a4fc-000c296aa366 | 192.168.1.12 |        3308 | ONLINE       |
| group_replication_applier | 18f64c9b-7223-11e9-bba2-000c293610f1 | 192.168.1.13 |        3308 | ONLINE       |
| group_replication_applier | 463679cf-7222-11e9-9459-000c29a6154a | 192.168.1.11 |        3306 | ONLINE       |
+---------------------------+--------------------------------------+--------------+-------------+--------------+

#查找主节点:
mysql> SHOW STATUS LIKE 'group_replication_primary_member';
+----------------------------------+--------------------------------------+
| Variable_name                    | Value                                |
+----------------------------------+--------------------------------------+
| group_replication_primary_member | 463679cf-7222-11e9-9459-000c29a6154a |
+----------------------------------+--------------------------------------+
或者 
select variable_value from performance_schema.global_status where variable_name = 'group_replication_primary_member';

这个时候从是只读的,在上执行SQL会报错:

ERROR 1290 (HY000): The MySQL server is running with the --super-read-only option so it cannot execute this statement

2、多写部署(单主切换到多主)
多主模式可以直接由单主模式切换, 需要在所有节点上先关闭组复制,设置 group_replication_single_primary_mode=OFF 等参数,再启动组复制。

# 停止组复制(所有节点执行):
mysql> stop group_replication;
#单主模式设置为ON,多主模式设置为OFF
mysql> set global group_replication_single_primary_mode=OFF;
#在所有节点启用多主数据更新的严格一致性检查
mysql> set global group_replication_enforce_update_everywhere_checks=ON;


# 随便选择某个节点执行(这里选择之前是从节点的1.12执行)
mysql> SET GLOBAL group_replication_bootstrap_group=ON;
mysql> START GROUP_REPLICATION;
mysql> SET GLOBAL group_replication_bootstrap_group=OFF;

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

mysql> SELECT * FROM performance_schema.replication_group_members;
+---------------------------+--------------------------------------+--------------+-------------+--------------+
| CHANNEL_NAME              | MEMBER_ID                            | MEMBER_HOST  | MEMBER_PORT | MEMBER_STATE |
+---------------------------+--------------------------------------+--------------+-------------+--------------+
| group_replication_applier | 0bbd0bcc-7223-11e9-a4fc-000c296aa366 | 192.168.1.12 |        3308 | ONLINE       |
| group_replication_applier | 18f64c9b-7223-11e9-bba2-000c293610f1 | 192.168.1.13 |        3308 | ONLINE       |
| group_replication_applier | 463679cf-7222-11e9-9459-000c29a6154a | 192.168.1.11 |        3306 | ONLINE       |
+---------------------------+--------------------------------------+--------------+-------------+--------------+

#多主模式,变量 group_replication_primary_member 为空(8.0版本会直接显示MEMBER_ROLE)
mysql> SHOW STATUS LIKE 'group_replication_primary_member';
+----------------------------------+-------+
| Variable_name                    | Value |
+----------------------------------+-------+
| group_replication_primary_member |       |
+----------------------------------+-------+
可以测试写入是多节点的

3、多主切换到单主模式

# 所有节点执行
mysql> stop group_replication;
mysql> set global group_replication_enforce_update_everywhere_checks=OFF;
mysql> set global group_replication_single_primary_mode=ON;


# 主节点(192.168.1.11)执行
SET GLOBAL group_replication_bootstrap_group=ON;
START GROUP_REPLICATION;
SET GLOBAL group_replication_bootstrap_group=OFF;
# 从节点(192.168.1.12、192.168.1.13)执行
START GROUP_REPLICATION;

三、节点加入

1.1 环境:(这里是在多主模式下加入,单主模式下亦然)
因为MGR也是使用的GTID,所以新节点的加入也是需要通过备份和binlog来进行恢复,然后加入组复制的。这里因为binlog都在,所以直接加入一个新安装的MySQL实例加入到组里。
_
1.2 新节点加入步骤

#新节点配置文件:
loose-group_replication_local_address= "192.168.1.14:33061"
loose-group_replication_group_seeds= "192.168.1.11:33061,192.168.1.12:33061,192.168.1.13:33061,192.168.1.14:33061"

#在其他三个节点执行:
set global group_replication_group_seeds='192.168.1.11:33061,192.168.1.12:33061,192.168.1.13:33061,192.168.1.14:33061';

#新节点加入:
set global group_replication_single_primary_mode=OFF;
set global group_replication_enforce_update_everywhere_checks=ON;
CHANGE MASTER TO MASTER_USER='repl', MASTER_PASSWORD='repl' FOR CHANNEL 'group_replication_recovery';

#查看所有节点:
mysql> SELECT * FROM performance_schema.replication_group_members;
+---------------------------+--------------------------------------+--------------+-------------+--------------+
| CHANNEL_NAME              | MEMBER_ID                            | MEMBER_HOST  | MEMBER_PORT | MEMBER_STATE |
+---------------------------+--------------------------------------+--------------+-------------+--------------+
| group_replication_applier | 0bbd0bcc-7223-11e9-a4fc-000c296aa366 | 192.168.1.12 |        3308 | ONLINE       |
| group_replication_applier | 18f64c9b-7223-11e9-bba2-000c293610f1 | 192.168.1.13 |        3308 | ONLINE       |
| group_replication_applier | 241b7e73-74d4-11e9-aef0-000c293af32c | 192.168.1.14 |        3308 | ONLINE       |
| group_replication_applier | 463679cf-7222-11e9-9459-000c29a6154a | 192.168.1.11 |        3306 | ONLINE       |
+---------------------------+--------------------------------------+--------------+-------------+--------------+

到此新节点已经加入。

四、故障转移

1、多主模式
_
第三部分新加入了节点的时候属于多主模式,所以首先来看看,当多主模式下,有节点发生了故障会如何处理。
从图中很容易看出来,一个节点fail了,写线程直接连接到其他的节点上了,因为所有节点都是读写的,所以也就存在选取哪个为主节点了。
这里直接将1.12这个节点的MySQL给kill掉,看看对组的影响:

#kill了1.12之后,很明显这个节点直接被移出了
mysql> SELECT * FROM performance_schema.replication_group_members;
+---------------------------+--------------------------------------+--------------+-------------+--------------+
| CHANNEL_NAME              | MEMBER_ID                            | MEMBER_HOST  | MEMBER_PORT | MEMBER_STATE |
+---------------------------+--------------------------------------+--------------+-------------+--------------+
| group_replication_applier | 18f64c9b-7223-11e9-bba2-000c293610f1 | 192.168.1.13 |        3308 | ONLINE       |
| group_replication_applier | 241b7e73-74d4-11e9-aef0-000c293af32c | 192.168.1.14 |        3308 | ONLINE       |
| group_replication_applier | 463679cf-7222-11e9-9459-000c29a6154a | 192.168.1.11 |        3306 | ONLINE       |
+---------------------------+--------------------------------------+--------------+-------------+--------------+

#给集群插入一些数据,再讲kill的节点重新加入组里
set global group_replication_single_primary_mode=OFF;
set global group_replication_enforce_update_everywhere_checks=ON;
START GROUP_REPLICATION;

可以发现新插入的数据同步到1.12节点了

2、单主模式
_
单主模式存在一个选取哪个为新主的过程,大体过程为:

通过安装字典顺序(使用其UUID)来排序剩余的server成员并选择列表中第一个成员来作为下一个 主节点。

先将多主模式切换到单主模式,查看节点情况:

#按照官方文档规则,单主模式下主fail了,应该是1.12这个server充当着
mysql> SELECT * FROM performance_schema.replication_group_members;
+---------------------------+--------------------------------------+--------------+-------------+--------------+
| CHANNEL_NAME              | MEMBER_ID                            | MEMBER_HOST  | MEMBER_PORT | MEMBER_STATE |
+---------------------------+--------------------------------------+--------------+-------------+--------------+
| group_replication_applier | 0bbd0bcc-7223-11e9-a4fc-000c296aa366 | 192.168.1.12 |        3308 | ONLINE       |
| group_replication_applier | 18f64c9b-7223-11e9-bba2-000c293610f1 | 192.168.1.13 |        3308 | ONLINE       |
| group_replication_applier | 241b7e73-74d4-11e9-aef0-000c293af32c | 192.168.1.14 |        3308 | ONLINE       |
| group_replication_applier | 463679cf-7222-11e9-9459-000c29a6154a | 192.168.1.11 |        3306 | ONLINE       |
+---------------------------+--------------------------------------+--------------+-------------+--------------+

mysql>  SHOW STATUS LIKE 'group_replication_primary_member';
+----------------------------------+--------------------------------------+
| Variable_name                    | Value                                |
+----------------------------------+--------------------------------------+
| group_replication_primary_member | 463679cf-7222-11e9-9459-000c29a6154a |
+----------------------------------+--------------------------------------+

#kill掉1.11这个主,看看哪个成为新的主
mysql> SELECT * FROM performance_schema.replication_group_members;
+---------------------------+--------------------------------------+--------------+-------------+--------------+
| CHANNEL_NAME              | MEMBER_ID                            | MEMBER_HOST  | MEMBER_PORT | MEMBER_STATE |
+---------------------------+--------------------------------------+--------------+-------------+--------------+
| group_replication_applier | 0bbd0bcc-7223-11e9-a4fc-000c296aa366 | 192.168.1.12 |        3308 | ONLINE       |
| group_replication_applier | 18f64c9b-7223-11e9-bba2-000c293610f1 | 192.168.1.13 |        3308 | ONLINE       |
| group_replication_applier | 241b7e73-74d4-11e9-aef0-000c293af32c | 192.168.1.14 |        3308 | ONLINE       |
+---------------------------+--------------------------------------+--------------+-------------+--------------+
#果然,1.12这台server成为了主
mysql> SHOW STATUS LIKE 'group_replication_primary_member';
+----------------------------------+--------------------------------------+
| Variable_name                    | Value                                |
+----------------------------------+--------------------------------------+
| group_replication_primary_member | 0bbd0bcc-7223-11e9-a4fc-000c296aa366 |
+----------------------------------+--------------------------------------+

#再要想加入1.11这台,按照之前加入节点的步骤就行了

参考:https://dev.mysql.com/doc/refman/5.7/en/group-replication.html

相关实践学习
如何在云端创建MySQL数据库
开始实验后,系统会自动创建一台自建MySQL的 源数据库 ECS 实例和一台 目标数据库 RDS。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助     相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
目录
相关文章
|
6月前
MGR会创建哪几个专属channel
MGR会创建哪几个专属channel》
41 2
|
SQL 算法 关系型数据库
MySQL-MGR部署
MySQL-MGR部署
182 0
MySQL-MGR部署
|
3月前
|
SQL 存储 关系型数据库
MGR你掌握了吗
MGR你掌握了吗
33 0
|
SQL 存储 运维
MySQL MGR 介绍 | 学习笔记
快速学习 MySQL MGR 介绍,介绍了 MySQL MGR 介绍系统机制, 以及在实际应用过程中如何使用。
MySQL MGR 介绍 | 学习笔记
|
算法 关系型数据库 MySQL
GreatSQL MGR优化参考
GreatSQL MGR优化参考
110 0
GreatSQL MGR优化参考
|
Java 调度 Spring
elastic-job之简单job
简介 elastic-job是当当网开源的基于zookeeper和quartz实现的分布式作业调度框架。github地址是https://github.com/dangdangdotcom/elastic-job,官方网站是http://elasticjob.io/。
2538 0
|
关系型数据库 MySQL 网络安全
『叶问』#39,都有哪些情况可能导致MGR服务无法启动
『叶问』#39,都有哪些情况可能导致MGR服务无法启动
158 0
|
关系型数据库 MySQL
应用MySQL MGR
对于MGR的维护,我以实验的方式分享给大家。
|
存储 关系型数据库 MySQL
MySQL 5.7 MGR部署
实现MySQL数据库主从强同步复制,保证主从库数据的强一致性,MySQL 5.7推出了MGR, 我以实验的方式给大家分享部署MGR。
|
关系型数据库 MySQL
如何优雅的添加MGR节点?
引言 MySQL Group Replication(简称MGR)是MySQL官方于2016年12月份推出的一个全新的高可用与高扩展的解决方案。MGR提供了高可用、高扩展、高可靠的MySQL集群服务,是MySQL数据库未来发展的一个重要方向。
4362 0