今天主要介绍MGR的特点和部署过程。
MySQL 组复制特点:提供了高可用性,高弹性,可靠的 MySQL 服务。实现了基于复制协议的多主更新。
1)复制组由多个 server成员构成,并且组中的每个 server 成员可以独立地执行事务。但所有读写(RW)事务只有在冲突检测成功后才会提交。只读(RO)事务不需要在冲突检测,可以立即提交。
2)对于任何 RW 事务,提交操作并不是由始发 server 单向决定的,而是由组来决定是否提交。准确地说,在始发 server 上,当事务准备好提交时,该 server 会广播写入值(已改变的行)和对应的写入集(已更新的行的唯一标识符)。然后会为该事务建立一个全局的顺序。最终,这意味着所有 server 成员以相同的顺序接收同一组事务。因此,所有 server 成员以相同的顺序应用相同的更改,以确保组内一致。
3)组复制够根据在一组 server 中复制系统的状态来创建具有冗余的容错系统。因此,只要它不是全部或多数 server 发生故障,即使有一些 server 故障,系统仍然可用,最多只是性能和可伸缩性降低,但它仍然可用。server 故障是孤立并且独立的。它们由组成员服务来监控,组成员服务依赖于分布式故障检测系统,其能够在任何 server 自愿地或由于意外停止而离开组时发出信号。他们是由一个分布式恢复程序来确保当有 server 加入组时,它们会自动更新组信息到最新。并且多主更新确保了即使在单个服务器故障的情况下也不会阻止更新,不必进行 server故障转移。因此,MySQL 组复制保证数据库服务持续可用。
4)值得注意的一点是,尽管数据库服务可用,但当有一个 server 崩溃时,连接到它的客户端必须定向或故障转移到不同的 server。
这不是组复制要解决的问题。连接器,负载均衡器,路由器或其他形式的中间件更适合处理这个问题。
MySQL Group Replication正是基于这些技术和概念,实现了一种多主全更新的复制协议。
一个Replication-group就是一组节点,每个节点都可以独立执行事务,而读写事务则会在于group内的其他节点进行协调之后再commit。因此,当一个事务准备提交时,会自动在group内进行原子性的广播,告知其他节点变更了什么内容/执行了什么事务。这种原子广播的方式,使得这个事务在每一个节点上都保持着同样顺序。这意味着每一个节点都以同样的顺序,接收到了同样的事务日志,所以每一个节点以同样的顺序重演了这些事务日志,最终整个group保持了完全一致的状态。然而,不同的节点上执行的事务之间有可能存在资源争用。这种现象容易出现在两个不同的并发事务上。假设在不同的节点上有两个并发事务,更新了同一行数据,那么就会发生资源争用。面对这种情况,GroupReplication判定先提交的事务为有效事务,会在整个group里面重演,后提交的事务会直接中断,或者回滚,最后丢弃掉。因此,这也是一个无共享的复制方案,每一个节点都保存了完整的数据副本组复制可以在两种模式下运行。
1.在单主模式下,组复制具有自动选主功能,每次只有一个 server成员接受更新。
2.在多主模式下,所有的 server 成员都可以同时接受更新.
MGR的限制
仅支持InnoDB表,并且每张表一定要有一个主键;
必须打开GTID特性,二进制日志格式必须设置为ROW;
二进制日志不支持binlog event checksum
目前一个MGR集群最多支持9个节点
事务写集合(Transaction write set extraction)必须打开。(这个目前与savepoint冲突,这也是导致mysqldump无法备份GR实例的原因
SERIALIZABLE 隔离级别不支持
并行执行DDL可能导致数据一致性等方面的错误,目前不支持在多节点同时执行同一对象的DDL
外键的级联约束操作目前的实现并不完全支持
主从复制限制
1.存储引擎必须为innodb
2.每个表必须提供主键
3.只支持ipv4,网络需求较高
4.一个group最多只能有9台服务器
5.不支持Replication event checksums,
6.不支持Savepoints
7.multi-primary mode部署方式不支持SERIALIZABLE事务隔离级别
8.multi-primary mode部署方式不能完全支持级联外键约束
9.multi-primary mode部署方式不支持在不同节点上对同一个数据库对象并发执行DDL
尽管数据库服务可用,但当有一个 server 崩溃时,连接到它的客户端必须定向或故障转移到不同的 server。这不是组复制要解决的问题。连接器,负载均衡器,路由器或其他形式的中间件更适合处理这个问题。
注意事项:
(1)把relay.info记录在slave_relay_log_info表里有两个好处:relay.info明文存储不安全,把relay.info中的信息记录在table中相对安全;可以避免relay.info更新不及时,SLAVE 重启后导致的主从复制出错。
(2)前面的用户密码修改和创建用户操作必须设置binlog不记录,执行后再打开,否则会引起START GROUP_REPLICATION执行报错:
my.cnf
#####通用选项######
#每台主机的server-id请设置的不一样
server-id=截取主机IP地址的最后一段
#####replication 复制配置###############
log-bin = /usr/local/mysql/mysql-bin
max_binlog_size=500M
binlog_format = row
sync_binlog=1
expire_logs_days=15
###group replication###########
gtid_mode=on
enforce_gtid_consistency= ON
master_info_repository = TABLE
relay_log_info_repository = TABLE
binlog_checksum = NONE
log_slave_updates = ON
#log_slave_updates是将从服务器从主服务器收到的更新记入到从服务器自己的二进制日志文件中。
transaction_write_set_extraction = XXHASH64
##server必须为每个事物收集写集合,使用XXHASH64哈希算法将其编码为散列
loose-group_replication_group_name ='aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa'
#组的名字可以随便起,但不能用主机的GTID
loose-group_replication_start_on_boot = off # #插件在server启动时不自动启动组复制
loose-group_replication_bootstrap_group = off #同上
loose-group_replication_local_address = '主机IP:33061' #写自己主机所在IP
loose-group_replication_group_seeds ='10.10.75.100:33061,10.10.75.101:33061,10.10.75.102:33061'
loose-group_replication_single_primary_mode = FALSE #关闭单主模式的参数
loose-group_replication_enforce_update_everywhere_checks = TRUE #开启多主模式的参数
####设置单主模式##########
loose-group_replication_single_primary_mode = true
loose-group_replication_enforce_update_everywhere_checks = false
执行命令
在node0和node1和node2 创建复制账号
set sql_log_bin=0;
create user rpl_user@'%';
grant replication slave on *.* to rpl_user@'%' identified by 'rpl_pass';
flush privileges;
set sql_log_bin=1;
修改账号密码,也要set sql_log_bin=0
/usr/local/mysql/bin/mysql -uroot -p123@abc
change master to master_user='rpl_user',master_password='rpl_pass' for channel 'group_replication_recovery';
组内每台主机,都需要先安装组复制插件.否则会导致启动失败.
mysql>INSTALL PLUGIN group_replication SONAME 'group_replication.so';
克隆的机器需要修改uuid,因为复制的机器uuid相同
配置完,重启mysql服务
node0节点上执行 启动组复制
set global group_replication_bootstrap_group=ON;
set global group_replication_ip_whitelist="192.168.59.0/24";
START GROUP_REPLICATION;
SELECT * FROM performance_schema.replication_group_members;
SET GLOBAL group_replication_bootstrap_group=OFF;
node1
set global group_replication_allow_local_disjoint_gtids_join=ON;
set global group_replication_ip_whitelist="192.168.59.0/24";
START GROUP_REPLICATION;
SELECT * FROM performance_schema.replication_group_members;
node2
set global group_replication_allow_local_disjoint_gtids_join=ON;
set global group_replication_ip_whitelist="192.168.59.0/24";
START GROUP_REPLICATION;
SELECT * FROM performance_schema.replication_group_members;
select * from performance_schema.replication_group_members;
查看集群状态,都为ONLINE就表示OK:
测试:
node0上创建测试库
create database mgr1;
use mgr1;
create table mgr1.t1(id int primary key, cn varchar(30));
insert into t1 values(1,'a');
node1上查看
use mgr1;
select * from t1;
node1上插入 insert into t1 values(2,'Tom');
node2上查看
node2上插入 insert into t1 values(3,'li');
模拟节点宕机
node1上,service mysql stop
node2上,继续插入数据
启动node1节点
service mysql start
mysql>
set global group_replication_allow_local_disjoint_gtids_join = on;
START GROUP_REPLICATION;
再次查看组成员,发现已重新加入组
mysql> SELECT * FROM performance_schema.replication_group_members;
注意:前面的用户密码修改和创建用户操作必须设置binlog不记录,执行后再打开,否则会引起START GROUP_REPLICATION执行报错:
报错信息如下:
ERROR 3092 (HY000): The server is not configured properly to be an active member of the group. Please see more details on error log
根据提示打开group_replication_allow_local_disjoint_gtids_join选项,mysql命令行执行:
mysql> set global group_replication_allow_local_disjoint_gtids_join=ON;
再次启动组复制
mysql> START GROUP_REPLICATION;
2、连不上master,报错信息如下:
2017-04-17T16:18:14.756191+08:00 25 [Warning] Storing MySQL user name or password information in the master info repository is not secure and is therefore not recommended. Please consider using the USER and PASSWORD connection options for START SLAVE; see the 'START SLAVE Syntax' in the MySQL Manual for more information.
2017-04-17T16:18:14.814193+08:00 25 [ERROR] Slave I/O for channel 'group_replication_recovery': error connecting to master'repl_user@host-192-168-99-156:3306' - retry-time: 60 retries: 1, Error_code: 2005
2017-04-17T16:18:14.814219+08:00 25 [Note] Slave I/O thread for channel 'group_replication_recovery' killed while connecting to master
2017-04-17T16:18:14.814227+08:00 25 [Note] Slave I/O thread exiting for channel 'group_replication_recovery', read up to log 'FIRST', position 4
2017-04-17T16:18:14.814342+08:00 19 [ERROR] Plugin group_replication reported: 'There was an error when connecting to the donor server. Check group replication recovery's connection credentials.'
解决方案:
添加映射
vim /etc/hosts
重启下组复制
mysql> stop group_replication;
Query OK, 0 rows affected (8.76 sec)
mysql> start group_replication;
Query OK, 0 rows affected (2.51 sec)
日常维护步骤:
1、如果从库某一节点关闭
stop group_replication;
2、如果所有的库都关闭后,第一个库作为主库首先执行
set global group_replication_bootstrap_group=ON;
start group_replication;
剩下的库直接执行即可!
set global group_replication_allow_local_disjoint_gtids_join=ON;
start group_replication;
3、如果主库故障,会自动从两个从库选出一个主库,主库启动后再次执行如下命令后会变成从库
start group_replication;
至此MGR搭建并验证完成