华子目录
组复制的特点
MySQL Group Replication(简称MGR)是MySQL官方于2016 年12月推出的一个全新的高可用与高扩展的解决方案组复制是MySQL 5.7.17版本出现的新特性,它提供了高可用、高扩展、高可靠的MySQL集群服务MySQL组复制分单主模式和多主模式,传统的mysql主从复制技术仅解决了数据同步的问题MGR对属于同一组中的服务器自动进行协调。对于要提交的事务,组成员必须就全局事务序列中给定事务的顺序达成一致提交或回滚事务由每个服务器单独完成(即每台服务器都可以写数据或读数据),但所有服务器都必须做出相同的决定- 如果存在
网络分区,导致成员无法达成事先定义的分割策略,则在解决此问题之前系统不会继续进行,这是一种内置的自动裂脑保护机制 MGR由组通信系统(Group Communication System ,GCS) 协议支持- 该
系统提供故障检测机制、组成员服务以及安全且有序的消息传递
组复制的工作原理

首先我们将多个节点共同组成一个复制组,在执行读写(RW)事务的时候,需要通过一致性协议层(Consensus层)的同意,也就是读写事务想要进行提交,就必须要经过组里"大多数人"(对应Node节点)的同意,大多数指的是同意的节点数量需要大于 (N/2+1),这样才可以进行提交,而不是原发起方一个说了算。而针对只读(RO)事务则不需要经过组内同意,直接提交即可
节点数量不能超过9台
单主模式和多主模式
单主

single-primary mode(单写或单主模式)单写模式group内只有一台节点可写可读,其他节点只可以读。当主服务器失败时,会自动选择新的主服务器
多主

multi-primary mode(多写或多主模式)组内的所有机器都是primary节点,同时可以进行读写操作,并且数据是最终一致的
实现mysql的多主模式的组复制
-
为了
避免出错,在所有节点中从新生成数据库数据 -
node1中
bash
[root@mysql-node1 ~]# /etc/init.d/mysqld stop
[root@mysql-node1 ~]# rm -rf /data/mysql/*
node2中
bash
[root@mysql-node2 ~]# /etc/init.d/mysql.server stop
[root@mysql-node2 ~]# rm -rf /data/mysql/*
node3中
bash
[root@mysql-node3 ~]# /etc/init.d/mysqld stop
[root@mysql-node3 ~]# rm -rf /data/mysql/*
修改master上的配置文件内容
bash
[root@mysql-node1 ~]# vim /etc/my.cnf
[mysqld]
datadir=/data/mysql
socket=/data/mysql/mysql.sock
symbolic-links=0
server-id=10 #配置server唯一标识号
disabled_storage_engines="MyISAM,BLACKHOLE,FEDERATED,ARCHIVE,MEMORY" #禁用指定存储引擎
gtid_mode=ON #启用全局事件标识
enforce_gtid_consistency=ON #强制gtid一致
master_info_repository=TABLE #复制事件数据到表中而不记录在数据目录中
relay_log_info_repository=TABLE
binlog_checksum=NONE #禁止对二进制日志校验
log_slave_updates=ON #打开数据库中继,当slave中sql线程读取日志后也会写入到自己的binlog中
log_bin=binlog #开启binlog日志并重新指定log名称
binlog_format=ROW #使用行日志格式
plugin_load_add='group_replication.so' #加载组复制插件
transaction_write_set_extraction=XXHASH64 #把每个事件编码为加密散列
group_replication_group_name="aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa" #通知插件正式加入,或创建的组名,名称为uuid格式
group_replication_start_on_boot=off #在server启动时不自动启动组复制
group_replication_local_address="172.25.254.10:33061" #指定插件接受其他成员的信息端口
group_replication_group_seeds="172.25.254.10:33061,172.25.254.20:33061,172.25.254.30:33061" #本地地址允许访问成员列表
group_replication_ip_whitelist="172.25.254.0/24,127.0.0.1/8" #主机白名单
group_replication_bootstrap_group=off #不随系统自启而启动
group_replication_single_primary_mode=OFF #使用多主模式
group_replication_enforce_update_everywhere_checks=ON #组同步中有任何改变检测更新
group_replication_allow_local_disjoint_gtids_join=1 #放弃自己信息以master事件为主
3台节点上配置hosts解析(这里ip解析的域名一定要和主机名一致)
sql
[root@mysql-node1 ~]# vim /etc/hosts
127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4
::1 localhost localhost.localdomain localhost6 localhost6.localdomain6
172.25.254.10 mysql-node1
172.25.254.20 mysql-node2
172.25.254.30 mysql-node3
sql
[root@mysql-node2 ~]# vim /etc/hosts
127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4
::1 localhost localhost.localdomain localhost6 localhost6.localdomain6
172.25.254.10 mysql-node1
172.25.254.20 mysql-node2
172.25.254.30 mysql-node3
sql
[root@mysql-node3 ~]# vim /etc/hosts
127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4
::1 localhost localhost.localdomain localhost6 localhost6.localdomain6
172.25.254.10 mysql-node1
172.25.254.20 mysql-node2
172.25.254.30 mysql-node3

master上进行初始化
bash
[root@mysql-node1 ~]# mysqld --user=mysql --initialize
master上启动数据库
bash
[root@mysql-node1 ~]# /etc/init.d/mysqld start
[root@mysql-node1 ~]# mysql -uroot -p'7t84Qherg)&U'
sql
mysql> alter user root@localhost identified by '123456';
- 进行
组复制配置
sql
mysql> set sql_log_bin=0;
mysql> create user huazi@'%' identified by '123456';
mysql> grant replication slave on *.* to huazi@'%';
mysql> flush privileges;
mysql> set sql_log_bin=1;
mysql> change master to master_user='huazi',master_password='123456' for channel 'group_replication_recovery';
mysql> set global group_replication_bootstrap_group=on;
mysql> start group_replication;
mysql> set global group_replication_bootstrap_group=off;
- 测试
sql
mysql> select * from performance_schema.replication_group_members;
+---------------------------+--------------------------------------+-------------+-------------+--------------+
| CHANNEL_NAME | MEMBER_ID | MEMBER_HOST | MEMBER_PORT | MEMBER_STATE |
+---------------------------+--------------------------------------+-------------+-------------+--------------+
| group_replication_applier | c0dd8ac3-b159-11ef-9d51-000c2928b963 | mysql-node1 | 3306 | ONLINE |
+---------------------------+--------------------------------------+-------------+-------------+--------------+
- 此时
组就做好了,但是这时,这个组是一个光杆司令,我们需要把别的主机加入到这个组中 - 在
node2上
sql
#先将node1上的my.cnf文件拷贝过来
[root@mysql-node1 ~]# rsync /etc/my.cnf root@172.25.254.20:/etc/
[root@mysql-node2 ~]# vim /etc/my.cnf

- 初始化
bash
[root@mysql-node2 ~]# mysqld --user=mysql --initialize
- 启动
mysql
bash
[root@mysql-node2 ~]# /etc/init.d/mysql.server start
sql
[root@mysql-node2 ~]# mysql -uroot -p'Pd=RovxmK6Oj'
mysql> alter user root@localhost identified by "123456";
- 进行
组复制配置
sql
mysql> set sql_log_bin=0;
mysql> create user huazi@'%' identified by "123456";
mysql> grant replication slave on *.* to huazi@'%';
mysql> flush privileges;
mysql> set sql_log_bin=1;
mysql> change master to master_user='huazi',master_password='123456' for channel 'group_replication_recovery';
mysql> start group_replication;
- 测试
sql
#我们发现node2加入到了组里
mysql> select * from performance_schema.replication_group_members;
+---------------------------+--------------------------------------+-------------+-------------+--------------+
| CHANNEL_NAME | MEMBER_ID | MEMBER_HOST | MEMBER_PORT | MEMBER_STATE |
+---------------------------+--------------------------------------+-------------+-------------+--------------+
| group_replication_applier | 79c39c85-b15d-11ef-b574-000c292fa568 | mysql-node2 | 3306 | ONLINE |
| group_replication_applier | c0dd8ac3-b159-11ef-9d51-000c2928b963 | mysql-node1 | 3306 | ONLINE |
+---------------------------+--------------------------------------+-------------+-------------+--------------+
- 在
node3上
sql
#先将node1上的my.cnf文件拷贝过来
[root@mysql-node1 ~]# rsync /etc/my.cnf root@172.25.254.30:/etc/
[root@mysql-node3 ~]# vim /etc/my.cnf

- 初始化
sql
[root@mysql-node3 ~]# mysqld --user mysql --initialize
- 启动
MySQL
sql
[root@mysql-node3 ~]# /etc/init.d/mysqld start
sql
[root@mysql-node3 ~]# mysql -uroot -p'&jTpm:rok9Pv'
mysql> alter user root@localhost identified by '123456';
- 进行
组复制配置
sql
mysql> set sql_log_bin=0;
mysql> create user huazi@'%' identified by "123456";
mysql> grant replication slave on *.* to huazi@'%';
mysql> flush privileges;
mysql> set sql_log_bin=1;
mysql> change master to master_user='huazi',master_password='123456' for channel 'group_replication_recovery';
mysql> start group_replication;
- 测试
sql
#我们发现,node3也加入到了组里
mysql> select * from performance_schema.replication_group_members;
+---------------------------+--------------------------------------+-------------+-------------+--------------+
| CHANNEL_NAME | MEMBER_ID | MEMBER_HOST | MEMBER_PORT | MEMBER_STATE |
+---------------------------+--------------------------------------+-------------+-------------+--------------+
| group_replication_applier | 747e4cef-b15f-11ef-a867-000c290eaf9d | mysql-node3 | 3306 | ONLINE |
| group_replication_applier | 79c39c85-b15d-11ef-b574-000c292fa568 | mysql-node2 | 3306 | ONLINE |
| group_replication_applier | c0dd8ac3-b159-11ef-9d51-000c2928b963 | mysql-node1 | 3306 | ONLINE |
+---------------------------+--------------------------------------+-------------+-------------+--------------+
测试
bash
#node1上创建一个库
mysql> create database huazi;
#node2上查看
mysql> show databases;
+--------------------+
| Database |
+--------------------+
| information_schema |
| huazi | #发现了创建的库
| mysql |
| performance_schema |
| sys |
+--------------------+
#node3上查看
mysql> show databases;
+--------------------+
| Database |
+--------------------+
| information_schema |
| huazi | #发现了创建的库
| mysql |
| performance_schema |
| sys |
+--------------------+
bash
#node3上创建一个表(在创建表时,必须存在主键,否则插入数据时会失败)
mysql> use huazi;
Database changed
mysql> create table userlist(
-> name varchar(10) primary key,
-> password varchar(20));
#node2上查看
mysql> use huazi;
Database changed
mysql> show tables;
+-----------------+
| Tables_in_huazi |
+-----------------+
| userlist |
+-----------------+
#node1上查看
mysql> use huazi;
Database changed
mysql> show tables;
+-----------------+
| Tables_in_huazi |
+-----------------+
| userlist |
+-----------------+
- 在创建表时,必须存在
主键,否则插入数据时会失败
bash
#node2上插入数据
mysql> insert into userlist values
-> ("huazi","123456");
#node3上查看
mysql> select * from userlist;
+-------+----------+
| name | password |
+-------+----------+
| huazi | 123456 |
+-------+----------+
#node1上查看
mysql> select * from userlist;
+-------+----------+
| name | password |
+-------+----------+
| huazi | 123456 |
+-------+----------+
- 总结:所有主机都是可读可写的
bash
#当有一台主机挂了
mysql> quit
Bye
[root@mysql-node2 ~]# /etc/init.d/mysql.server stop
#我们在node1上可以发现,挂了的主机自动从组中消除了
mysql> select * from performance_schema.replication_group_members;
+---------------------------+--------------------------------------+-------------+-------------+--------------+
| CHANNEL_NAME | MEMBER_ID | MEMBER_HOST | MEMBER_PORT | MEMBER_STATE |
+---------------------------+--------------------------------------+-------------+-------------+--------------+
| group_replication_applier | 747e4cef-b15f-11ef-a867-000c290eaf9d | mysql-node3 | 3306 | ONLINE |
| group_replication_applier | c0dd8ac3-b159-11ef-9d51-000c2928b963 | mysql-node1 | 3306 | ONLINE |
+---------------------------+--------------------------------------+-------------+-------------+--------------+
bash
#当主机上线后
[root@mysql-node2 ~]# /etc/init.d/mysql.server start
#也不会自动加进去,需要我们手动加入
mysql> select * from performance_schema.replication_group_members;
+---------------------------+--------------------------------------+-------------+-------------+--------------+
| CHANNEL_NAME | MEMBER_ID | MEMBER_HOST | MEMBER_PORT | MEMBER_STATE |
+---------------------------+--------------------------------------+-------------+-------------+--------------+
| group_replication_applier | 747e4cef-b15f-11ef-a867-000c290eaf9d | mysql-node3 | 3306 | ONLINE |
| group_replication_applier | c0dd8ac3-b159-11ef-9d51-000c2928b963 | mysql-node1 | 3306 | ONLINE |
+---------------------------+--------------------------------------+-------------+-------------+--------------+
- 为什么需要
手动加入呢

bash
#进行手动加入
[root@mysql-node2 ~]# mysql -uroot -p
Enter password:
#手动加入
mysql> start group_replication;
#我们发现加入了
mysql> select * from performance_schema.replication_group_members;
+---------------------------+--------------------------------------+-------------+-------------+--------------+
| CHANNEL_NAME | MEMBER_ID | MEMBER_HOST | MEMBER_PORT | MEMBER_STATE |
+---------------------------+--------------------------------------+-------------+-------------+--------------+
| group_replication_applier | 747e4cef-b15f-11ef-a867-000c290eaf9d | mysql-node3 | 3306 | ONLINE |
| group_replication_applier | 79c39c85-b15d-11ef-b574-000c292fa568 | mysql-node2 | 3306 | ONLINE |
| group_replication_applier | c0dd8ac3-b159-11ef-9d51-000c2928b963 | mysql-node1 | 3306 | ONLINE |
+---------------------------+--------------------------------------+-------------+-------------+--------------+