华子目录
组复制
的特点
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 |
+---------------------------+--------------------------------------+-------------+-------------+--------------+