介绍

MGR (MySQL Group Replication) 是 MySQL 5.7.17 提出的,既可以很好的保证数据一致性又可以自动切换,具备故障检测功能、支持多节点写入。是以插件的形式提供,可以灵活部署。

MySQL MGR 集群是多个 MysQL Server 节点共同组成的分布式集群,每个 Server 都有完整的副本,它是基于 ROW 格式的二进制日志文件和 GTID 特性来实现的。

 

MGR复制与传统复制的区别:

异步复制:复制性能没有损耗,主库提交事务不需要从库的确认,数据一致性没法保证。

半同步复制:主库提交事务需要等待从库的确认,复制性能会有损耗,保证数据一致性

MGR复制:组复制采用Paxos分布式算法以及原子消息广播,主节点提交的事务会原子广播write set(由唯一标识以及更新的数据组成)到其他节点进行验证,由于采用原子广播的技术,全部节点要么全部接收或者全部没有接受,如果出现两个以上的事务操作同一行数据,产生数据冲突,会采用提交时间优先的原则,假设t1以及t2同时更新相同的一行数据,t2的提交操作在t1之前,则发生数据冲突时,t1的数据会被回滚,复制性能会有损坏,保证数据一致性。

 

 

 

 

MGR 的优点

  • 强一致性:基于原生复制及 Paxos 协议的组复制技术(以插件形式提供),确保数据的严格一致性。
  • 高容错性:在少数节点故障时仍可正常运行,具备自动故障检测机制。节点间资源冲突采用无锁设计(如先到者优先)处理,避免错误。
  • 高扩展性:支持节点动态自动加入与移除。新节点加入后自动同步数据至一致状态;节点移除后,集群自动更新并维护组配置信息。
  • 高灵活性:支持单主模式与多主模式。单主模式下自动选举主节点,所有写操作路由至主节点;多主模式下,所有节点均可并发处理写操作。

MGR 的一些限制

  • 仅支持 InnoDB 表,并且每个表一定要有一个主键。
  • 必须打开 GTID 特性,二进制日志格式必须设置为 ROW 。
  • MGR 不支持大事务。
  • 仅支持 IPv4 网络,组大小限制为最少3个节点、最多9个节点。
  • 不支持外键。
  • 二进制日志不支持 Binlog Event Checksum 。
  • 所有节点 server_id 和 server_uuid 需唯一。

 

 

部署

 

每个节点目录结构

mkdir  {conf,data}

[root@noce1 MGR]# tree
.
├── conf
│   └── my.cnf
├── data
└──  mysql.yml

所有环境禁用防火墙和SElinux

 

 

一、准备部署文件

1.1 所有节点都准备

[mysqld]
server-id=1  #每个节点唯一标识
log-bin=mysql-bin-1.log 
binlog-format=ROW   
gtid-mode=ON
enforce-gtid-consistency=ON
log-slave-updates=ON
binlog-checksum=NONE
master-info-repository=TABLE
relay-log-info-repository=TABLE
transaction-write-set-extraction=XXHASH64
#以下MGR配置
loose-group-replication-group-name=aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee
loose-group-replication-start-on-boot=OFF
loose-group-replication-local-address=192.168.1.10:33061  #本机ip
loose-group-replication-group-seeds=192.168.1.10:33061,192.168.1.20:33061,192.168.1.30:33061  #所有节点ip
loose-group-replication-bootstrap-group=OFF   
loose-group-replication-single-primary-mode=ON
loose-group-replication-enforce-update-everywhere-checks=OFF

server-id需修改

log-bin=mysql-bin-1.log      行级 binlog,MGR 硬性要求 ROW 格式。

enforce-gtid-consistency   CREATE TEMPORARY TABLECREATE TABLE ... SELECT),MGR 强制要求打开,否则无法启动组复制。binlog-checksumCRC32,保持默认即可,但旧版本必须显式设置为 NONE

group-name给整个 MGR 组起一个全局唯一的名字(UUID 格式),三个节点相同。

start-on-bootMySQL           实例启动时不自动启动 Group Replication 插件,这个参数如果设置为 OFF,当坏掉的节点修复后,不会自动加入集群。

local-address需修改

group-seed  种子列表,告诉当前节点“初次加入组时可以去找谁”。只要列表中的任意一个节点在线,新节点就能拿到完整的成员信息并加入组。通常把所有成员都写上,方便任何顺序启动。需修改

bootstrap-group(这个配置可不改,通过下面sql形式进行开关)

single-primary-mode            打开单主模式(Single-Primary),组内只有一台节点可写(primary),其余为只读(secondaries),主节点故障时自动重新选举

enforce-update-everywhere-checks       在多主模式下才生效;单主模式可保持 OFF

 

1.2 准备启动文件

version: '3.8'
services:
  mysql1:   
    image: mysql:8.0.39
    container_name: mysql
    hostname: mysql1  #每个节(mysql1、mysql2、mysql3)
    command: ["mysqld"]
    environment:
      MYSQL_ROOT_PASSWORD: 123456789
    volumes:
      - ./data/:/var/lib/mysql
      - ./conf/my.cnf:/etc/mysql/conf.d/mysql-master.cnf
    extra_hosts:   #绑定DNS解析域名,不然无法转移故障
      mysql1: 192.168.1.10
      mysql2: 192.168.1.20
      mysql3: 192.168.1.30
    healthcheck:
      test: ["CMD", "mysqladmin", "ping", "-h", "localhost", "-u", "root", "-p$$MYSQL_ROOT_PASSWORD"]
      interval: 10s
      timeout: 5s
      retries: 5
    network_mode: "host"      #需用host网络模式

MySQL 节点端口 :3306

MGR 通信端口:33061

 

二、启动

docker compose -f mysql.yml up -d

 

 

三、集群初始化

3.1 进入容器 进入数据库

docker exec -it mysql bash 
mysql -uroot -p123456789

 

 

3.2 每个节点都要执行

-- 创建复制用户
CREATE USER 'repl'@'%' IDENTIFIED WITH mysql_native_password BY '123456';
GRANT REPLICATION SLAVE ON *.* TO 'repl'@'%';
GRANT BACKUP_ADMIN ON *.* TO 'repl'@'%';
FLUSH PRIVILEGES;

reset master;

 

3.3 上面执行完在执行下面。每个节点都要

INSTALL PLUGIN group_replication SONAME 'group_replication.so';

 

 

四、启动集群

4.1 主节点执行

CHANGE MASTER TO MASTER_USER='repl', MASTER_PASSWORD='123456' FOR CHANNEL 'group_replication_recovery'; 
SET GLOBAL group_replication_bootstrap_group=ON; 
START GROUP_REPLICATION; SET GLOBAL group_replication_bootstrap_group=OFF;

SELECT * FROM performance_schema.replication_group_members;

 

4.2 从节点执行,上面执行完最好等10秒

CHANGE MASTER TO MASTER_USER='repl', MASTER_PASSWORD='123456' FOR CHANNEL 'group_replication_recovery';
START GROUP_REPLICATION;

SELECT * FROM performance_schema.replication_group_members;

 

 

五、测试高可用

直接停用master节点

docker stop mysql1

可以看到 mysql2 成为了新主

通过日志查看

 

 

六、恢复集群

模拟节点挂掉。并修改了数据

6.1 在集群挂掉时,我新建了一个dddd的数据库

6.2 启动原master

docker start mysql1

 

 

6.3 在原master节点执行

STOP GROUP_REPLICATION;
RESET MASTER;
CHANGE MASTER TO MASTER_USER='repl', MASTER_PASSWORD='123456' FOR CHANNEL 'group_replication_recovery';
START GROUP_REPLICATION;

 

执行完可以在其他节点发现 源master已经加入节点,但已经变成了从节点

 

在源master节点查看数据。可以发现。 新增的库 也自动同步过来了

 

 

注意:集群部署不成功, 大部分是文档有遗漏的地方,仔细检查。可以通过mysql日志查看

 

 

到此MGR结束