vlambda博客
学习文章列表

运维工程师:MySQL5.7 MGR集群搭建

目录

一:MGR介绍

二:部署MGR一主多从集群

三:Multi-primary多主模式实现多节点同

       时读写


No.1

  MGR介绍



1.1  MGR集群简介


MySQL Group Replication(简称MGR)是MySQL官方于2016年12月推出的一个全新的高可用与高扩展的解决方案。MySQL组复制提供了高可用、高扩展、高可靠的MySQL集群服务。


1.2  MGR的特点


高一致性,基于原生复制及paxos协议的组复制技术,并以插件的方式提供,提供一致数据安全保证;

What's Group Replication(什么是组复制?)


先说主从复制,一主多从,主库提供读写功能,从库提供读功能。当一个事务在master 提交成功时,会把binlog文件同步到从库服务器上落地为relay log给slave端执行,这个过程主库是不考虑从库是否有接收到binlog文件,有可能出现这种情况,当主库commit一个事务后,数据库发生宕机,刚好它的binlog还没来得及传送到slave端,这个时候选任何一个slave端都会丢失这个事务,造成数据不一致情况。原理图如下:


运维工程师:MySQL5.7 MGR集群搭建


为了避免出现主从数据不一致的情况,MySQL引入了半同步复制,添加多了一个从库反馈机制,这个有两种方式设置:


主库执行完事务后,同步binlog给从库,从库ack反馈接收到binlog,主库提交commit,反馈给客户端,释放会话;


主库执行完事务后,主库提交commit ,同步binlog给从库,从库ack反馈接收到binlog,反馈给客户端,释放会话;


运维工程师:MySQL5.7 MGR集群搭建


但是,问题来了,虽然满足了一主多从,读写分离,数据一致,但是,依旧有两个弊端:

写操作集中在MASTER服务器上;

MASTER宕机后,需要人为选择新主并重新给其他的slave端执行change master(可自行写第三方工具实现,但是mysql的复制就是没提供,所以也算是弊端)于是,官方于2016年12月12日正式发布了MySQL Group Replication  


MySQL Group Replication可以提供哪些功能呢?

1. 多主,在同一个group里边的所有实例,每一个实例可以执行写操作,也就是每个实例都执行Read-Write。


需要注意的是,多主情况下,当执行一个事务时,需要确保同个组内的每个实例都认可这个事务无冲突异常,才可以commit,如果设置的是单主,其他实例ReadOnly,则不需要进行上面的判断。


多主情况下,事务并发冲突问题就凸显出来了,如何避免呢?数据库内部有一个认证程序,当不同实例并发对同一行发起修改,在同个组内广播认可时,会出现并发冲突,那么会按照先执行的提交,后执行的回滚。


2. 弹性,同个Group Replication中,节点的加入或者移除都是自动调整;如果新加入一个节点,该节点会自动从Group的其他节点同步数据,直到与其他节点一致;如果移除一个节点,那么剩下的实例会自动更新,不再向这个节点广播事务操作,当然,这里要注意,假设一个Group的节点有n个(max(n)=9,同个Group最多节点数为9),移除或者宕机的节点数应该小于等于 floor((n-1)/2) ,注意是向下取整;如果是单主模式,宕机的是单主,则人为选择新主后,其他节点也会自动从新主同步数据。


3. 更高性能的同步机制

运维工程师:MySQL5.7 MGR集群搭建


一个复制组由若干个节点(数据库实例)组成,组内各个节点维护各自的数据副本(Share Nothing),通过一致性协议实现原子消息和全局有序消息,来实现组内实例数据的一致。


扩展:paxos协议

1、Paxos用于解决分布式系统中一致性问题。分布式一致性算法(Consensus Algorithm)是一个分布式计算领域的基础性问题,其最基本的功能是为了在多个进程之间对某个(某些)值达成一致(强一致);


简单来说就是确定一个值,一旦被写入就不可改变。paxos用来实现多节点写入来完成一件事情,例如mysql主从也是一种方案,但这种方案有个致命的缺陷,如果主库挂了会直接影响业务,导致业务不可写,从而影响整个系统的高可用性。paxos协议只是一个协议,不是具体的一套解决方案。目的是解决多节点写入问题。


paxos协议用来解决的问题可以用一句话来简化:将所有节点都写入同一个值,且被写入后不再更改。


2、高容错性,只要不是大多数节点坏掉就可以继续工作,有自动检测机制,当不同节点产生资源争用冲突时,不会出现错误,按照先到者优先原则进行处理,并且内置了自动化脑裂防护机制;


3、高扩展性,节点的新增和移除都是自动的,新节点加入后,会自动从其他节点上同步状态,直到新节点和其他节点保持一致,如果某节点被移除了,其他节点自动更新组信息,自动维护新的组信息;


4、高灵活性,有单主模式和多主模式,单主模式下,会自动选主,所有更新操作都在主上进行;多主模式下,所有server都可以同时处理更新操作。MGR是MySQL数据库未来发展的一个重要方向。


小结:高一致性,高容错性,高扩展性,高灵活性


1.3  MGR基础结构要求


1)引擎必须为innodb,因为需要事务支持在commit时对各节点进行冲突检查


2)每个表必须有主键,在进行事务冲突检测时需要利用主键值对比


3)必须开启binlog且为row格式


4)开启GTID,且主从状态信息存于表中

--master-info-repository=TABLE 、

--relay-log-info-repository=TABLE、

--log-slave-updates打开


什么是GTID?

GTID(Global Transaction ID)是对于一个已提交事务的编号,并且是一个全局唯一的编号。


GTID实际上是由UUID+TID组成的。其中UUID是一个MySQL实例的唯一标识。TID代表了该实例上已经提交的事务数量,并且随着事务提交单递增。下面是一个GTID的具体形式,

3E11FA47-71CA-11E1-9E33-C80AA9429562:23


5)一致性检测设置--transaction-write-set-extraction=XXHASH64


1.4  MGR使用限制:


1. 和普通复制binlog校验不能共存,需设置--binlog-checksum=none


2. 不支持gap lock(间隙锁),隔离级别需设置为read_committed


3. 不支持对表进行锁操作(lock /unlock table),不会发送到其他节点执行 ,影响需要对表进行加锁操作的情况,列入mysqldump全表备份恢复操作


4. 不支持serializable(序列化)隔离级别


5. DDL语句不支持原子性,不能检测冲突,执行后需自行校验是否一致

不支持外键:多主不支持,单主模式不存在此问题

最多支持9个节点:超过9台server无法加入组


No.2

部署MGR一主多从集群



2.1  环境准备


数据库服务器规划

序号 IP地址        主机名     数据库端口号 Server ID  操作系统1   192.168.1.63  xuegod63 MySQL-5.7.24 3306 100   CentOS 7.52   192.168.1.62  xuegod62 MySQL-5.7.24 3306 101   CentOS 7.53   192.168.1.64  xuegod64 MySQL-5.7.24 3306 102   CentOS 7.5 


2.2  安装mysql


所有节点安装

上传mysql-5.7.tar.gz到Linux主机上,并解压:

注:mysql-5.7.tar.gz  中包括了安装mysql5.7主要的软件包。 这样部署起来更方便。

[root@xuegod63 ~]# scp mysql-5.7.tar.gz xuegod62.cn:/root/[root@xuegod63 ~]# scp mysql-5.7.tar.gz xuegod64.cn:/root/


安装mysql

注:所有mysql节点全部安装,由于临时密码不同,此处省略62、64节点安装初始化过程

[root@xuegod63 ~]# tar xvf mysql-5.7.tar.gz[root@xuegod63 ~]# yum -y install ./mysql*.rpm[root@xuegod63 ~]# systemctl start mysqld    #启动MySQL会生成临时密码。


在MySQL的配置文件/etc/my.cnf 中关闭密码强度审计插件,并重启MySQl服务。

[root@xuegod63 ~]# vim /etc/my.cnf   #修改MySQL的配置文件,在[myqld]标签处末行添加以下项:validate-password=OFF      #不使用密码强度审计插件[root@xuegod63 ~]# systemctl restart mysqld  #重启MySQL服务[root@xuegod63 ~]# grep 'password'  /var/log/mysqld.log   #获取临时密码。2018-08-01T09:59:33.918961Z 1 [Note] A temporary password is generated for root@localhost: buL.UJp!T2Od    #临时密码[root@xuegod63 ~]# mysql -u root -p'buL.UJp!T2Od'  #使用临时密码登录MySQl,注意临时密码要引号mysql> set password for root@localhost = password('123456');  #修改root用户密码为123456mysql> flush privileges;


2.3  配置主机名解析


在三台数据库服务器上都设置ip与主机名的对应关系: 

[root@xuegod63 ~]# vim /etc/hosts192.168.1.62    xuegod62192.168.1.63    xuegod63192.168.1.64    xuegod64[root@xuegod63 ~]# scp /etc/hosts xuegod62:/etc/hosts[root@xuegod63 ~]# scp /etc/hosts xuegod64:/etc/hosts


2.4  配置xuegod63主节点


group_name可以通过uuidgen生成

[root@xuegod63 ~]# uuidgence9be252-2b71-11e6-b8f4-00212844f856[root@xuegod63 ~]# vim /etc/my.cnf


 #在  [mysqld] 配置组中,增加以下红色内容:

[mysqld]server_id = 1    #服务IDgtid_mode = ON    #全局事务enforce_gtid_consistency = ON       #强制GTID的一致性master_info_repository = TABLE      #将master.info元数据保存在系统表中relay_log_info_repository = TABLE    #将relay.info元数据保存在系统表中binlog_checksum = NONE    #禁用二进制日志事件校验log_slave_updates = ON    #级联复制log_bin = binlog     #开启二进制日志记录binlog_format = ROW    #以行的格式记录plugin_load_add='group_replication.so'  transaction_write_set_extraction=XXHASH64  #使用哈希算法将其编码为散列group_replication_group_name="ce9be252-2b71-11e6-b8f4-00212844f856"  #加入的组名group_replication_start_on_boot=off  #不自动启用组复制集群group_replication_local_address="xuegod63:33061"   #以本机端口33061接受来自组中成员的传入连接group_replication_group_seeds="xuegod63:33061, xuegod62:33062, xuegod64:33063"  #组中成员访问表group_replication_bootstrap_group=off  #不启用引导组


#这些设置将服务器配置为使用唯一标识符编号1,启用全局事务标识符,并将复制元数据存储在系统表而不是文件中。此外,它还指示服务器打开二进制日志记录,使用基于行的格式并禁用二进制日志事件校验和。


# plugin load add将组复制插件添加到服务器启动时加载的插件列表中。在生产部署中,这比手动安装插件更可取。


group_replication_group_name的值必须是有效的UUID。在二进制日志中为组复制事件设置GTID时,此UUID在内部使用。可以使用SELECT UUID()生成UUID。


将group_replication_start_on_boot变量配置为off会指示插件在服务器启动时不会自动启动操作。这在设置组复制时很重要,因为它确保您可以在手动启动插件之前配置服务器。配置成员后,您可以将组启动时的组复制设置为打开,以便在服务器启动时自动启动组复制。


配置group_replication_bootstrap_group指示插件是否引导组。在这种情况下,即使xuegod63是组的第一个成员,我们在选项文件中将此变量设置为off。相反,我们在实例运行时配置:

group_replication_bootstrap_group,以确保只有一个成员实际引导组。


group_replication_bootstrap_group变量在任何时候都只能在属于某个组的一个服务器实例上启用,通常是在您第一次引导该组时启用(或者在整个组关闭并再次备份的情况下)。如果多次引导组,例如当多个服务器实例设置了此选项时,则它们可能会创建一个人工分割大脑场景,其中存在两个具有相同名称的不同组。在第一个服务器实例联机后,始终将group_replication_bootstrap_group设置为off。


#什么是元数据

元数据(Metadata),又称中介数据、中继数据,为描述数据的数据(data about data),主要是描述数据属性(property)的信息,用来支持如指示存储位置、历史数据、资源查找、文件记录等功能。元数据算是一种电子式目录,为了达到编制目录的目的,必须在描述并收藏数据的内容或特色,进而达成协助数据检索的目的。


#什么是级联复制

级联复制(cascade):是指从主场地复制过来的又从该场地再次复制到其他场地,即A场地把数据复制到B场地,B场地又把这些数据或其中部分数据再复制到其他场地。


重启MySQL服务

[root@xuegod63 ~]# systemctl restart mysqld


服务器xuegod63.cn上建立复制账号:

[root@xuegod63 ~]# mysql -u root -p123456mysql> set SQL_LOG_BIN=0;    #停掉日志记录mysql> grant replication slave on *.* to repl@'192.168.1.%' identified by '123456';#创建一个用户repl,后期用于其他节点,同步数据。mysql> flush privileges;mysql> set SQL_LOG_BIN=1;   #开启日志记录


注:为什么创建repl用户需要关闭二进制日志功能? 创建成功后,再开启?

因为,用于同步数据的用户名repl和密码,必须在所有节点上有,且用户名和密码必须一样。所有,创建用户和密码时,先关闭二进制日志功能,这样不产生二进制日志数据。创建成功后,再开启二进制日志功能。这样repl用户信息,每台机器上都有了,而且不会在MGR同步数据时产生冲突。


mysql> change master to master_user='repl',master_password='123456'  for channel 'group_replication_recovery';    #构建group replication集群


查看MySQL服务器xuegod63.cn上安装的group replication插件,这个组件在my.cnf配置文件中,plugin_load_add='group_replication.so'   有指定

mysql> show plugins;


运维工程师:MySQL5.7 MGR集群搭建


如果没有安装成功,可以执行这个命令,手动再次安装:安装插件

mysql> install PLUGIN group_replication SONAME 'group_replication.so';


启动服务器:

xuegod63.cn上MySQL的group replication

设置group_replication_bootstrap_group为ON,表示,这台机器是集群中的master,以后加入集群的服务器都是salve。引导只能由一台服务器完成。

mysql> set global group_replication_bootstrap_group=ON;


作为首个节点启动mgr集群

mysql> start group_replication;mysql> set global group_replication_bootstrap_group=OFF;

#启动成功后,这台服务器已经是master了。有了master后,引导器就没有用了,就可以关闭了。


查看mgr的状态

查询表:

performance_schema.replication_group_membersmysql> select * from performance_schema.replication_group_members;


运维工程师:MySQL5.7 MGR集群搭建


测试服务器xuegod63.cn上的MySQL

mysql> create database test;Query OK, 1 row affected (0.01 sec)mysql> use test;Database changedmysql> create table t1 (id int primary key,name varchar(20));  #注意创建主键Query OK, 0 rows affected (0.01 sec)mysql> insert into t1 values (1,'man');Query OK, 1 row affected (0.01 sec)mysql> select * from t1;+----+------+| id  | name |+----+------+|  1 | man  |+----+------+1 row in set (0.00 sec)mysql> show binlog events;


运维工程师:MySQL5.7 MGR集群搭建


2.5  集群中添加xuegod62主机


复制组添加新实例xuegod62.cn

修改/etc/my.cnf 配置文件,方法和之前相同。

[root@xuegod64 ~]# vim /etc/my.cnf   #在mysqld配置,追加以下内容[mysqld]server_id=2  #注意服务ID不能一样gtid_mode=ONenforce_gtid_consistency=ONmaster_info_repository=TABLErelay_log_info_repository=TABLEbinlog_checksum=NONElog_slave_updates=ONlog_bin=binlogbinlog_format=ROWplugin_load_add='group_replication.so'transaction_write_set_extraction=XXHASH64group_replication_group_name="ce9be252-2b71-11e6-b8f4-00212844f856"  #这保持和master一样group_replication_start_on_boot=offgroup_replication_local_address="xuegod62:33062"   #这里写xuegod62主机名group_replication_group_seeds="xuegod63:33061, xuegod62:33062, xuegod64:33063"group_replication_bootstrap_group=off


重启MySQL服务

[root@xuegod62 ~]# systemctl restart mysqld


用户授权

[root@xuegod62 ~]# mysql -u root -p123456mysql> set SQL_LOG_BIN=0;   #停掉日志记录mysql> grant replication slave on *.* to repl@'192.168.1.%' identified by '123456';mysql> flush privileges;mysql> set SQL_LOG_BIN=1;  #开启日志记录mysql> change master to master_user='repl',master_password='123456'  for channel 'group_replication_recovery';        #构建group replication集群


把实例添加到之前的复制组

mysql> set global group_replication_allow_local_disjoint_gtids_join=ON;Query OK, 0 rows affected (0.00 sec)mysql> start group_replication;Query OK, 0 rows affected (6.65 sec)


在xuegod63.cn上查看复制组状态

mysql> select * from performance_schema.replication_group_members;


运维工程师:MySQL5.7 MGR集群搭建


在新加的实例上查看数据库发现test库和t1表已同步

mysql> select * from test.t1;+----+-------+| id  | name |+----+-------+|  1 | man   |+----+-------+1 row in set (0.00 sec)


2.6  集群中添加xuegod64主机


详细步骤请参考复制组添加新实例xuegod64.cn, 这里只给出配置文件/etc/my.cnf:

[root@xuegod64 ~]# vim /etc/my.cnf[mysqld]server_id=3  #注意服务id不一样gtid_mode=ONenforce_gtid_consistency=ONmaster_info_repository=TABLErelay_log_info_repository=TABLEbinlog_checksum=NONElog_slave_updates=ONlog_bin=binlogbinlog_format=ROWplugin_load_add='group_replication.so'transaction_write_set_extraction=XXHASH64group_replication_group_name="ce9be252-2b71-11e6-b8f4-00212844f856"group_replication_start_on_boot=offgroup_replication_local_address="xuegod64:33063"group_replication_group_seeds="xuegod63:33061, xuegod62:33062, xuegod64:33063"group_replication_bootstrap_group=off


重启MySQL服务

[root@xuegod64 ~]# systemctl restart mysqld


用户授权

[root@xuegod64 ~]# mysql -u root -p123456mysql> set SQL_LOG_BIN=0;   #停掉日志记录mysql> grant replication slave on *.* to repl@'192.168.1.%' identified by '123456';mysql> flush privileges;mysql> set SQL_LOG_BIN=1;  #开启日志记录mysql> change master to master_user='repl',master_password='123456'  for channel 'group_replication_recovery';  #构建group replication集群


安装group replication插件

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


把实例添加到之前的复制组:

mysql> set global group_replication_allow_local_disjoint_gtids_join=ON;Query OK, 0 rows affected (0.00 sec)mysql> start group_replication;Query OK, 0 rows affected (6.65 sec)


在xuegod63.cn上查看复制组状态:

mysql> select * from performance_schema.replication_group_members;


运维工程师:MySQL5.7 MGR集群搭建

以上单master节点的集群就搭建完毕!


2.7  测试MGR一主多从读写功能


xuegod63查看集群参数设置列表:

mysql> show variables like 'group_replication%';


运维工程师:MySQL5.7 MGR集群搭建


查看xuegod63是否只读,发现xuegod63 master,可读可写。

mysql> show variables like '%read_only%';


运维工程师:MySQL5.7 MGR集群搭建


另外两台查看,发现xuegod64和xuegod62,是只读的

mysql>  show variables like '%read_only%';


运维工程师:MySQL5.7 MGR集群搭建


No.3

Multi-primary多主模式实现多节点同时读写



由单主模式修改为多主模式方法:

1、关闭xuegod63单主模式,在原来单主模式的主节点执行操作如下:

[root@xuegod63 ~]# mysql -u root -p123456mysql> stop GROUP_REPLICATION;mysql> set global group_replication_single_primary_mode=OFF;#关闭单master模式mysql> set global group_replication_enforce_update_everywhere_checks=ON;


#设置多主模式下各个节点严格一致性检查

#执行多点写入了,多点写入会存在冲突检查,这耗损性能挺大的,官方建议采用网络分区功能,在程序端把相同的业务定位到同一节点,尽量减少冲突发生几率。


mysql> SET GLOBAL group_replication_bootstrap_group=ON;mysql> START GROUP_REPLICATION;mysql> SET GLOBAL group_replication_bootstrap_group=OFF;


2、xuegod62,执行下面的操作即可

[root@xuegod62 ~]# mysql -u root -p123456mysql> stop GROUP_REPLICATION;mysql> set global group_replication_allow_local_disjoint_gtids_join=ON;


#即使,含有组中不存在的事务,也允许当前server加入组。

mysql> set global group_replication_single_primary_mode=OFF;mysql> set global group_replication_enforce_update_everywhere_checks=ON;mysql> start group_replication;查看效果mysql> show variables like '%read_only%';


运维工程师:MySQL5.7 MGR集群搭建

read_only 为off


3、xuegod64,执行下面的操作即可

[root@xuegod62 ~]# mysql -u root -p123456mysql> stop GROUP_REPLICATION;mysql> set global group_replication_allow_local_disjoint_gtids_join=ON;#即使,含有组中不存在的事务,也允许当前server加入组。mysql> set global group_replication_single_primary_mode=OFF;mysql> set global group_replication_enforce_update_everywhere_checks=ON;mysql> start group_replication;查看效果mysql> show variables like '%read_only%';


运维工程师:MySQL5.7 MGR集群搭建

read_only 为off


4、查看集群,3个节都正常

mysql> select * from performance_schema.replication_group_members;


运维工程师:MySQL5.7 MGR集群搭建


5.测试Multi-primary多主模式实现多节点同时读写

xuegod63上执行:mysql> insert into test.t1 values (2,'mk');xuegod62上执行:mysql> insert into test.t1 values (3,'cd');xuegod64上执行:mysql> insert into test.t1 values (4,'yum');mysql> select * from test.t1;+----+------+| id | name |+----+------+|  1 | man  ||  2 | mk   ||  3 | cd   ||  4 | yum  |+----+------+

总结:到此MGR,多主同时读写,已经完成。


扩展: 回顾

数据库热备份和集群演变过程如下:

运维工程师:MySQL5.7 MGR集群搭建
运维工程师:MySQL5.7 MGR集群搭建
运维工程师:MySQL5.7 MGR集群搭建
运维工程师:MySQL5.7 MGR集群搭建
运维工程师:MySQL5.7 MGR集群搭建

往期推荐