MySQL5.7 MGR 集群搭建
Posted 笨小孩@GF 知行合一
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了MySQL5.7 MGR 集群搭建相关的知识,希望对你有一定的参考价值。
MGR 介绍
MGR 集群简介:
mysql Group Replication(简称 MGR)是 MySQL 官方于 2016 年 12 月推出的一个全新的高可用与高扩展的解决方案。MySQL 组复制提供了高可用、高扩展、高可靠的 MySQL 集群服务。
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((n1)/2) ,注意向下取整;如果是单主模式,宕机的是单主,则人为选择新主后,其他节点也会自动从新主同步数据。
3. 更高性能的同步机制
- 一个复制组由若干个节点(数据库实例)组成,组内各个节点维护各自的数据副本(Share Nothing),通过一致性协议实现原子消息和全局有序消息,来实现组内实例数据的一致。
扩展:paxos 协议
Paxos 用于解决分布式系统中一致性问题。分布式一致性算法(Consensus Algorithm)是一个分布式计算领域的基础性问题,其最基本的功能是为了在多个进程之间对某个(某些)值达成一致(强一
致);简单来说就是确定一个值,一旦被写入就不可改变。paxos 用来实现多节点写入来完成一件事情,例如 mysql 主从也是一种方案,但这种方案有个致命的缺陷,如果主库挂了会直接影响业务,导致业务不可写,从而影响整个系统的高可用性。 - paxos 协议只是一个协议,不是具体的一套解决方案。目的是解决多节点写入问题。
- paxos 协议用来解决的问题可以用一句话来简化:
- 1、将所有节点都写入同一个值,且被写入后不再更改。
2、高容错性,只要不是大多数节点坏掉就可以继续工作,有自动检测机制,当不同节点产生资源争用冲突时,不会出现错误,按照先到者优先原则进行处理,并且内置了自动化脑裂防护机制;
3、高扩展性,节点的新增和移除都是自动的,新节点加入后,会自动从其他节点上同步状态,直到新节点和其他节点保持一致,如果某节点被移除了,其他节点自动更新组信息,自动维护新的组信息;
4、高灵活性,有单主模式和多主模式,单主模式下,会自动选主,所有更新操作都在主上进行;多主模式下,所有 server 都可以同时处理更新操作。
MGR 是 MySQL 数据库未来发展的一个重要方向。
小结:高一致性,高容错性,高扩展性,高灵活性 - MGR 基础结构要求
1)引擎必须为 innodb,因为需事务支持在 commit 时对各节点进行冲突检查
2)每个表必须有主键,在进行事务冲突检测时需要利用主键值对比
3)必须开启 binlog 且为 row 格式
4)开启 GTID,且主从状态信息存于表中(--master-info-repository=TABLE 、--relay-loginfo-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
MGR 使用限制:
1. 和普通复制 binlog 校验不能共存,需设置--binlog-checksum=none
2. 不支持 gap lock(间隙锁),隔离级别需设置为 read_committed
3. 不支持对表进行锁操作(lock /unlock table),不会发送到其他节点执行 ,影响需要对表进行加锁操作的情况,列入 mysqldump 全表备份恢复操作
4. 不支持 serializable(序列化)隔离级别
5. DDL 语句不支持原子性,不能检测冲突,执行后需自行校验是否一致不支持外键:多主不支持,单主模式不存在此问题,最多支持 9 个节点:超过 9 台 server 无法加入组
部署 MGR 集群
-
数据库服务器规划
- c7_2_3 192.168.2.3 Server version: 5.7.25 CentOS 7.6
- c7_2_5 192.168.2.5 Server version: 5.7.25 CentOS 7.5
- c7_2_5 192.168.2.5 Server version: 5.7.25 CentOS 7.6
- firewalld、iptables以及selinux均为关闭状态
- 所有节点安装 mysql-5.7.25
-
配置主机名解析在三台数据库服务器上都设置:(必须)
vim /etc/hosts
127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4 ::1 localhost localhost.localdomain localhost6 localhost6.localdomain6
192.168.2.3 c7_2_3
192.168.2.5 c7_2_5
192.168.2.6 c7_2_6 - 必须配置,否则后续会报错
-
配置节点 192.168.2.3
-
vim /etc/my.cnf
[mysqld]
datadir=/var/lib/mysql
socket=/var/lib/mysql/mysql.sock# Group Replication
server_id = 1
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
transaction_write_set_extraction = XXHASH64
loose-group_replication_group_name = 'e61bdb2a-6258-4843-97ff-4aee1ca1a270'
loose-group_replication_start_on_boot = off
loose-group_replication_local_address = 'c7_2_3:33061'
loose-group_replication_group_seeds ='c7_2_3:33061,c7_2_5:33061,c7_2_6:33061'
loose-group_replication_bootstrap_group = off
relay-log-recovery=1
loose-group_replication_single_primary_mode = off
loose-group_replication_enforce_update_everywhere_checks = on - [mysqld]
# Group Replication
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 #以行的格式记录
transaction_write_set_extraction = XXHASH64 #使用哈希算法将其编码为散列
loose-group_replication_group_name = 'e61bdb2a-6258-4843-97ff-4aee1ca1a270' #加入的组名,所有节点必须保持一致
loose-group_replication_start_on_boot = off #不自动启用组复制集群
loose-group_replication_local_address ='c7_2_3:33061' #以本机端口 33061 接受来自组中成员的传入连接
loose-group_replication_group_seeds = ''c7_2_3:33061', 'c7_2_5:33061', 'c7_2_6:33061'' #组中成员访问表
loose-group_replication_bootstrap_group = off #不启用引导组
group_name 可以通过 uuidgen 生成
- 重启 MySQL 服务
systemctl restart mysqld - 建立复制账号:
mysql -uroot -p123456
mysql> set SQL_LOG_BIN=0; #停掉日志记录
mysql> grant replication slave on *.* to slave@'192.168.2.%' identified by '123456';
mysql> flush privileges;
mysql> set SQL_LOG_BIN=1; #开启日志记录
mysql> change master to master_user='slave',master_password='123456' for channel 'group_replication_recovery'; #构建 group replication 集群
在 MySQL 服务器上安装 group replication 插件
mysql> install PLUGIN group_replication SONAME 'group_replication.so';
查看 group replication 组件
mysql> show plugins;
- 设置 group_replication_bootstrap_group 为 ON 是为了标示以后加入集群的服务器以这台服务器为基准,以后加入的就不需要设置。
mysql> set global group_replication_bootstrap_group=ON;
作为首个节点启动 mgr 集群
mysql> start group_replication;
mysql> set global group_replication_bootstrap_group=OFF;
查看 mgr 的状态
查询表 performance_schema.replication_group_members
mysql> select * from performance_schema.replication_group_members;
-
查看 gtid,所有节点必须保持一致
- show global variables like '%gtid%';
-
查看是否可以写入,多主模式下所有节点必须保持一致
- show variables like '%read_only%';
- 测试服务器 192.168.2.3 上的 MySQL
- 创建数据库、表并插入一些信息
- > create database mydata;
- > use test;
- > create table mylist (id int primary key,name varchar(20)); #注意创建主键
- > insert into mylist values (1,'man');
- > select * from mylist;
-
查看某个binlog日志内容
- show binlog events;
-
集群中添加 192.168.2.5 主机
复制组添加新实例 192.168.2.5
修改/etc/my.cnf 配置文件,方法和之前相同 -
vim /etc/my.cnf
datadir=/var/lib/mysql
socket=/var/lib/mysql/mysql.sock# Group Replication
server_id = 2
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
transaction_write_set_extraction = XXHASH64
loose-group_replication_group_name = 'e61bdb2a-6258-4843-97ff-4aee1ca1a270'
loose-group_replication_start_on_boot = ON
loose-group_replication_local_address = 'c7_2_5:33061'
loose-group_replication_group_seeds = 'c7_2_3:33061,c7_2_5:33061,c7_2_6:33061'
loose-group_replication_bootstrap_group = off
relay-log-recovery=1
group_replication_single_primary_mode = off
group_replication_enforce_update_everywhere_checks = ON
- 重启 MySQL 服务
systemctl restart mysqld
用户授权
mysql -u root -p123456
mysql> set SQL_LOG_BIN=0; #停掉日志记录
mysql> grant replication slave on *.* to slave@'192.168.2.%' identified by '123456';
mysql> flush privileges;
mysql> set SQL_LOG_BIN=1; #开启日志记录
mysql> change master to master_user='slave',master_password='123456' for channel 'group_replication_recovery'; #构建 group replication 集群
安装 group replication 插件
mysql> install PLUGIN group_replication SONAME 'group_replication.so';
把实例添加到之前的复制组
mysql> set global group_replication_allow_local_disjoint_gtids_join=ON;
mysql> start group_replication;
在 192.168.2.3 和 192.168.2.5上查看复制组状态
mysql> select * from performance_schema.replication_group_members;
- 查看之前创建的库和表是否同步
- 测试 在 192.168.2.5 上插入一些数据
- 集群中添加 192.168.2.6 主机
详细步骤请参考复制组添加新实例 192.168.2.5 -
vim /etc/my.cnf
[mysqld]
datadir=/var/lib/mysql
socket=/var/lib/mysql/mysql.sock
server_id = 3
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
transaction_write_set_extraction = XXHASH64
loose-group_replication_group_name = 'e61bdb2a-6258-4843-97ff-4aee1ca1a270'
loose-group_replication_start_on_boot = ON
loose-group_replication_local_address = 'c7_2_6:33061'
loose-group_replication_group_seeds = 'c7_2_3:33061,c7_2_5:33061,c7_2_6:33061'
loose-group_replication_bootstrap_group = off
group_replication_single_primary_mode = off
group_replication_enforce_update_everywhere_checks = ON
- 重启 MySQL 服务
systemctl restart mysqld
用户授权
mysql -u root -p123456
mysql> set SQL_LOG_BIN=0; #停掉日志记录
mysql> grant replication slave on *.* to slave@'192.168.2.%' identified by '123456';
mysql> flush privileges;
mysql> set SQL_LOG_BIN=1; #开启日志记录
mysql> change master to master_user='slave',master_password='123456' for channel 'group_replication_recovery'; #构建 group replication 集群
安装 group replication 插件
mysql> install PLUGIN group_replication SONAME 'group_replication.so';
把实例添加到之前的复制组
mysql> set global group_replication_allow_local_disjoint_gtids_join=ON;
mysql> start group_replication;
在 192.168.2.3 和 192.168.2.5上查看复制组状态
mysql> select * from performance_schema.replication_group_members;
- 测试 在 192.168.2.6 上插入、删除一些数据
- 在 192.168.2.5 上查看
- 在 192.168.2.5 上删除数据
-
模拟故障
- 停止 192.168.2.3 的mysql 服务
- 尝试在 192.168.2.5 和 2.6 上插入数据
- 读写正常,下面恢复刚才宕机的 192.168.2.3
- 每次恢复宕机,都需要重新加入组
- 模拟故障,服务器全部重启
- 尝试加入先前的组发现报错
- 重新创建组并加入
- 在其他节点上添加服务器
- 测试查询、插入、删除
- 在 192.168.2.6 上插入数据
- 在 192.168.2.5 上删除数据
以上是关于MySQL5.7 MGR 集群搭建的主要内容,如果未能解决你的问题,请参考以下文章