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;


  • 集群中添加 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 集群搭建的主要内容,如果未能解决你的问题,请参考以下文章

MGR集群搭建

手把手教你搭建Mysql8.0.22 MGR高可用集群

MySQL5.7之PXC集群搭建

MySQL MGR集群单主模式的自动搭建和自动化故障修复

MySQl高可用集群搭建(MGR + ProxySQL + Keepalived)

MySQL集群搭建--多主模式