运维工程师: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端都会丢失这个事务,造成数据不一致情况。原理图如下:
为了避免出现主从数据不一致的情况,MySQL引入了半同步复制,添加多了一个从库反馈机制,这个有两种方式设置:
主库执行完事务后,同步binlog给从库,从库ack反馈接收到binlog,主库提交commit,反馈给客户端,释放会话;
主库执行完事务后,主库提交commit ,同步binlog给从库,从库ack反馈接收到binlog,反馈给客户端,释放会话;
但是,问题来了,虽然满足了一主多从,读写分离,数据一致,但是,依旧有两个弊端:
写操作集中在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. 更高性能的同步机制
一个复制组由若干个节点(数据库实例)组成,组内各个节点维护各自的数据副本(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.5
2 192.168.1.62 xuegod62 MySQL-5.7.24 3306 101 CentOS 7.5
3 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用户密码为123456
mysql> flush privileges;
2.3 配置主机名解析
在三台数据库服务器上都设置ip与主机名的对应关系:
[root@xuegod63 ~]# vim /etc/hosts
192.168.1.62 xuegod62
192.168.1.63 xuegod63
192.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 ~]# uuidgen
ce9be252-2b71-11e6-b8f4-00212844f856
[root@xuegod63 ~]# vim /etc/my.cnf
#在 [mysqld] 配置组中,增加以下红色内容:
[mysqld]
server_id = 1 #服务ID
gtid_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 -p123456
mysql> 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;
如果没有安装成功,可以执行这个命令,手动再次安装:安装插件
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_members
mysql> select * from performance_schema.replication_group_members;
测试服务器xuegod63.cn上的MySQL
mysql> create database test;
Query OK, 1 row affected (0.01 sec)
mysql> use test;
Database changed
mysql> 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;
2.5 集群中添加xuegod62主机
复制组添加新实例xuegod62.cn
修改/etc/my.cnf 配置文件,方法和之前相同。
[root@xuegod64 ~]# vim /etc/my.cnf #在mysqld配置,追加以下内容
[mysqld]
server_id=2 #注意服务ID不能一样
gtid_mode=ON
enforce_gtid_consistency=ON
master_info_repository=TABLE
relay_log_info_repository=TABLE
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" #这保持和master一样
group_replication_start_on_boot=off
group_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 -p123456
mysql> 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;
在新加的实例上查看数据库发现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=ON
enforce_gtid_consistency=ON
master_info_repository=TABLE
relay_log_info_repository=TABLE
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="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 -p123456
mysql> 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;
以上单master节点的集群就搭建完毕!
2.7 测试MGR一主多从读写功能
xuegod63查看集群参数设置列表:
mysql> show variables like 'group_replication%';
查看xuegod63是否只读,发现xuegod63 master,可读可写。
mysql> show variables like '%read_only%';
另外两台查看,发现xuegod64和xuegod62,是只读的
mysql> show variables like '%read_only%';
No.3
Multi-primary多主模式实现多节点同时读写
由单主模式修改为多主模式方法:
1、关闭xuegod63单主模式,在原来单主模式的主节点执行操作如下:
[root@xuegod63 ~]# mysql -u root -p123456
mysql> 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 -p123456
mysql> 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%';
read_only 为off
3、xuegod64,执行下面的操作即可
[root@xuegod62 ~]# mysql -u root -p123456
mysql> 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%';
read_only 为off
4、查看集群,3个节都正常
mysql> select * from performance_schema.replication_group_members;
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,多主同时读写,已经完成。
扩展: 回顾
数据库热备份和集群演变过程如下:
往期推荐