MySQL Group Replication简述
MySQL 组复制实现了基于复制协议的多主更新(单主模式)。
复制组由多个 server成员构成,并且组中的每个 server 成员可以独立地执行事务。但所有读写(RW)事务只有在冲突检测成功后才会提交。只读(RO)事务不需要在冲突检测,可以立即提交。
对于任何 RW 事务,提交操作并不是由始发 server 单向决定的,而是由组来决定是否提交。准确地说,在始发 server 上,当事务准备好提交时,该 server 会广播写入值(已改变的行)和对应的写入集(已更新的行的唯一标识符)。然后会为该事务建立一个全局的顺序。最终,这意味着所有 server 成员以相同的顺序接收同一组事务。因此,所有 server 成员以相同的顺序应用相同的更改,以确保组内一致。
组复制使您能够根据在一组 server 中复制系统的状态来创建具有冗余的容错系统。因此,只要它不是全部或多数 server 发生故障,即使有一些 server 故障,系统仍然可用,最多只是性能和可伸缩性降低,但它仍然可用。server 故障是孤立并且独立的。它们由组成员服务来监控,组成员服务依赖于分布式故障检测系统,其能够在任何 server 自愿地或由于意外停止而离开组时发出信号。
他们是由一个分布式恢复程序来确保当有 server 加入组时,它们会自动更新组信息到最新。并且多主更新确保了即使在单个服务器故障的情况下也不会阻止更新,不必进行 server故障转移。因此,MySQL 组复制保证数据库服务持续可用。
值得注意的一点是,尽管数据库服务可用,但当有一个 server 崩溃时,连接到它的客户端必须定向或故障转移到不同的 server。 这不是组复制要解决的问题。连接器,负载均衡器,路由器或其他形式的中间件更适合处理这个问题。MySQL 组复制提供了高可用性,高弹性,可靠的 MySQL 服务。 MySQL组复制的一些限制:
1 不支持XA事务
2 表需要有主键
3 采用GTID+binlog的方式进行复制
4 只支持IPV4的网络
5 网络性能对于集群影响很大 ,需要低延迟,高带宽
6 多主不支持同一对象但是不同实例的并发的DDL+DML混合操作
7 不支持串行化操作 不支持RR模式的间隙锁,最好采用RC模式配合组复制
8 多主不支持外键约束
9 不支持事务保存点
10 集群性能取决于最差的硬件机器,所以推荐所有硬件统一配置
11 mysqldump无法备份GR实例
12 目前集群限制最多允许9个节点。
以上参考了网络上一些博客,原理的东西网上东西还是很多的,大家可以自行百度。
关于组复制的一些详细加强,可以看一下我们星耀队的译文MySQL 8.0.2复制新特性(翻译)
1:安装环境
机器 | IP |
---|---|
SERVER1 | 172.16.16.31 |
SERVER2 | 172.16.16.34 |
SERVER3 | 172.16.16.35 |
MySQL的版本是5.7.20,我们先在三台主机安装好MySQL并且启动,详细安装参考MySQL5.7.20编译安装,基本环境搭建完成以后我们来看一下MySQL Group Replication的配置
2:配置安装MySQL Group Replication
我们现在三台机器上已经配置好了三台MySQL服务,我们要在我们当前配置文件的基础上加上GR的一些参数,我们以SERVER1为例:
# GR 配置项 其中loose前缀表示若Group Replication plugin未加载 mysql server仍继续启动
binlog_checksum=NONE #MGR本身不支持binlog的checksum校验
transaction_write_set_extraction=XXHASH64
group_replication_group_name="00e575aa-0cc0-11e8-9186-0050569341db" # 组名
group_replication_start_on_boot=off # 在mysqld启动时不自动启动组复制
group_replication_local_address="172.16.16.35:24901"
group_replication_group_seeds="172.16.16.34:24901,172.16.16.35:24901,172.16.16.31:24901"
group_replication_bootstrap_group=off
我们之前已经加过一些必须的参数了,我们看看GR需要的其他参数:
gtid-mode=on
enforce_gtid_consistency = ON #GTID模式是组复制的基础技术
master_info_repository = TABLE
relay_log_info_repository = TABLE #管理复制的元数据和恢复用,记录同步的信息,便于管理和恢复
log-bin=row #必须是ROW格式
log_slave_updates = ON #需要记录事务的binlog,用作以后的恢复用,哪怕不是写入点,也需要
接下来我们要创建GR所使用的账号:
set sql_log_bin=0;
GRANT REPLICATION SLAVE,REPLICATION CLIENT ON *.* TO 'repl'@'%' IDENTIFIED BY '';
flush privileges;
set sql_log_bin=1;
我们先在主库执行:
CHANGE MASTER TO MASTER_USER='repl', MASTER_PASSWORD='' FOR CHANNEL 'group_replication_recovery';
INSTALL PLUGIN group_replication SONAME 'group_replication.so';
set global group_replication_allow_local_disjoint_gtids_join=ON;
START GROUP_REPLICATION;
然后在SERVER2,和server3上执行:
INSTALL PLUGIN group_replication SONAME 'group_replication.so';
START GROUP_REPLICATION;
然后去看一下节点:
mysql> select * from performance_schema.replication_group_members;
ERROR 2006 (HY000): MySQL server has gone away
No connection. Trying to reconnect...
Connection id: 145
Current database: mxq +---------------------------+--------------------------------------+-------------+-------------+--------------+
| CHANNEL_NAME | MEMBER_ID | MEMBER_HOST | MEMBER_PORT | MEMBER_STATE |
+---------------------------+--------------------------------------+-------------+-------------+--------------+
| group_replication_applier | 096769f1-de4e-11e7-bc85-0050569355e1 | sdw1 | 3306 | ONLINE |
| group_replication_applier | 6899e4bf-de91-11e7-a3bb-005056930bed | sdw2 | 3306 | ONLINE |
| group_replication_applier | c6b0f3b3-de40-11e7-9dbd-0050569341db | mdw | 3306 | ONLINE |
+---------------------------+--------------------------------------+-------------+-------------+--------------+
3 rows in set (0.00 sec)
我们可以通过查看MEMBER_STATE来确认节点的状态:
online
offline 离线
recoving 恢复中
unreachable 不可到达,查看错误日志
error 同步发生错误,查看错误日志
查看一下主节点是那个:
mysql> SELECT b.member_id, b.member_host, b.member_port FROM performance_schema.global_status a JOIN performance_schema.replication_group_members b
-> ON a.variable_value = b.member_id WHERE a.variable_name= 'group_replication_primary_member';
+--------------------------------------+-------------+-------------+
| member_id | member_host | member_port |
+--------------------------------------+-------------+-------------+
| c6b0f3b3-de40-11e7-9dbd-0050569341db | mdw | 3306 |
+--------------------------------------+-------------+-------------+
1 row in set (0.00 sec)
我们可以看到现在主节点是SERVER1,GR当中所有的从节点都是默认为read_only的。我们也可以通过以下系统表来检测GR的信息:
mysql> select * from performance_schema.replication_group_member_stats\G
*************************** 1. row ***************************
CHANNEL_NAME: group_replication_applier
VIEW_ID: 15181587863063562:15
MEMBER_ID: c6b0f3b3-de40-11e7-9dbd-0050569341db
COUNT_TRANSACTIONS_IN_QUEUE: 0
COUNT_TRANSACTIONS_CHECKED: 0
COUNT_CONFLICTS_DETECTED: 0
COUNT_TRANSACTIONS_ROWS_VALIDATING: 0
TRANSACTIONS_COMMITTED_ALL_MEMBERS: 00e575aa-0cc0-11e8-9186-0050569341db:1-17
LAST_CONFLICT_FREE_TRANSACTION:
1 row in set (0.00 sec)
我们可以看到现在的三台机器是单主模式的,我们把他修改为多主模式的话怎么改呢,但是我们强烈建议不要使用多主模式 ,因为多主模式下很容易hang住整个集群,而且很多的限制都是限制多主模式,如果我们要把单主修改为多主,只用做如下操作就好:
SERVER2,SERVER3:
STOP GROUP_REPLICATION;
SET GLOBAL group_replication_single_primary_mode=FALSE;
SET GLOBAL group_replication_enforce_update_everywhere_checks=TRUE;
SERVER1:
STOP GROUP_REPLICATION;
SET GLOBAL group_replication_single_primary_mode=FALSE;
SET GLOBAL group_replication_enforce_update_everywhere_checks=TRUE;
SET GLOBAL group_replication_bootstrap_group=on;
START GROUP_REPLICATION;
SET GLOBAL group_replication_bootstrap_group=off;
然后SERVER2,SERVER3:
START GROUP_REPLICATION;
我们在查看一下节点信息:
mysql> select * from performance_schema.replication_group_members;
+---------------------------+--------------------------------------+-------------+-------------+--------------+
| CHANNEL_NAME | MEMBER_ID | MEMBER_HOST | MEMBER_PORT | MEMBER_STATE |
+---------------------------+--------------------------------------+-------------+-------------+--------------+
| group_replication_applier | 096769f1-de4e-11e7-bc85-0050569355e1 | sdw1 | 3306 | ONLINE |
| group_replication_applier | 6899e4bf-de91-11e7-a3bb-005056930bed | sdw2 | 3306 | ONLINE |
| group_replication_applier | c6b0f3b3-de40-11e7-9dbd-0050569341db | mdw | 3306 | ONLINE |
+---------------------------+--------------------------------------+-------------+-------------+--------------+
3 rows in set (0.00 sec)
发现三个节点已经全部OK了,做一下测试:
SERVER1:
mysql> use mxq;
Database changed
mysql> create table gr(id int ,name varchar(10),primary key(id));
Query OK, 0 rows affected (0.06 sec) mysql> insert into gr(1,'a');
ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '1,'a')' at line 1
mysql> insert into gr values(1,'a');
Query OK, 1 row affected (0.05 sec)
SERVER2:
mysql> insert into gr values(2,'a');
Query OK, 1 row affected (0.01 sec)
SERVER3:
mysql> insert into gr values(3,'a');
Query OK, 1 row affected (0.04 sec)
然后查看数据:
mysql> select * from gr;
+----+------+
| id | name |
+----+------+
| 1 | a |
| 2 | a |
| 3 | a |
+----+------+
3 rows in set (0.00 sec)
这样就OK了。
从多主模式修改为单主模式
SERVER2,SERVER3:
STOP GROUP_REPLICATION;
SET GLOBAL group_replication_enforce_update_everywhere_checks=OFF;
SET GLOBAL group_replication_single_primary_mode=TRUE;
SERVER1:
STOP GROUP_REPLICATION;
SET GLOBAL group_replication_enforce_update_everywhere_checks=OFF;
SET GLOBAL group_replication_single_primary_mode=TRUE;
SET GLOBAL group_replication_bootstrap_group=on;
START GROUP_REPLICATION;
SET GLOBAL group_replication_bootstrap_group=off;
然后SERVER2,SERVER3:
START GROUP_REPLICATION;
这样就OK了。