MySQL异步复制技术
1. 主从复制
传统的MySQL复制提供了一个简单的主从复制方法。一个主节点,一个或多个从节点。主节点执行事务、提交事务,然后异步将所作的操作发送给从节点,从节点重放这些操作。所有的节点默认都具有一个数据的完整拷贝。

传统的 MySQL 主从复制架构是 MySQL 保持数据一致性的最基本架构,如下图所示,从库给主库发起读数据请求后,主库会通过 dump线程把 binlog 日志文件推送给从库,从库的 I/O 线程把接收到数据更新到 relay log,之后从库的 SQL 线程把 relay log 应用为 binlog 日志,直到主库与从库的 binlog 日志文件完全数据一致,达到主从同步。

该架构模式下:应用发来的事务请求,经过执行之后写入 binlog,主库把 binlog日志推送给从库,主库不需要等到从库是否成功更新数据到 relay log,主库直接提交事务即可。
这种模式牺牲了数据一致性,不能很好保证主从数据一致性。
2. 半同步复制
除了异步复制,还有半同步复制,它在异步复制基础上添加了一个同步操作。主节点需要等待从节点的ack回复,然后才能提交事务。

一主两从半同步架构,应用发来的事务请求,在主库执行后写入binlog,主库把binlog日志推送给两个从库,半同步主库需要等待其中任意一个从库更新数据到relay log成功并且告知主库,主库才提交事务,这样保证至少有一个从库同步上数据了,也缩短了延迟时间,保证了数据安全。
该模也存在两个问题:
MySQL无法自动切换,需要借助外力切库,运维复杂。
从库Slave的读压力太大会导致复制延迟不断增加。
Group Replication
为了解决以上问题,组复制应运而,MGR(MySQL Group Replication)是是MySQL官方推出的一款高可用与高扩展的解决方案,是多个 MySQL Server 节点共同组成的分布式集群,每个 Server 都有完整的数据副本;它是基于 ROW格式的二进制日志文件和 GTID 特性;
1. Group Replication特点
MGR提供了高可用、高扩展、高可靠的MySQL集群服务,具有以下特点:
强一致性:基于原生复制和paxos协议,保证数据传输的一致性和原子性;
高容错性:只要大多数节点没有出现故障,集群就可对外提供服务;
高扩展性:节点的加入和移除都是自动的,不需要人为过多干预;
高灵活性:具有单主模式和多主模式,单主模式在主宕机后自动选主,多主模式多节点写入。
2. Group Replication限制
仅支持InnoDB表,并且每张表一定要有一个主键,用于做write set的冲突检测;
必须打开GTID特性,二进制日志格式必须设置为ROW,用于选主与write set;
COMMIT可能会导致失败,类似于快照事务隔离级别的失败场景;
目前一个MGR集群最多支持9个节点;
不支持外键于save point特性,无法做全局间的约束检测与部分部分回滚;
二进制日志不支持binlog event checksum。
Group Replication配置实践
以下为MGR配置过程实践,配置安装MySQL过程此处不再赘述.当前环境如下:
主机名 | IP | 版本 |
MGR01 | 192.168.79.13 | 8.0.29 |
MGR02 | 192.168.79.14 | 8.0.30 |
MGR03 | 192.168.79.15 | 8.0.31 |
三节点设置如下参数:
####: for binlog
binlog_format =row
log_bin =/data/mysql-8.0/binary/mysql-bin
binlog_checksum =none
####: for gtid
gtid_mode =on
enforce_gtid_consistency =on
####: for replication
master_info_repository =table
relay_log_info_repository =table
slave_parallel_type =logical_clock
slave_parallel_workers =4
#MGR
plugin_load_add=group_replication.so
transaction_write_set_extraction =XXHASH64
group_replication_group_name ="3db33b36-0e51-409f-a61d-c99756e90155"
group_replication_start_on_boot =off
group_replication_local_address = "192.168.79.159:33061"
group_replication_group_seeds = "192.168.79.157:33061,192.168.79.158:33061,192.168.79.159:33061"
group_replication_bootstrap_group = off
# mgr for multi master
group_replication_single_primary_mode =off
group_replication_enforce_update_everywhere_checks =on
# mgr more set
binlog_transaction_dependency_tracking = WRITESET
配置MGR必须开启gtid和binlog;
group_replication_group_name 集群名字,各个节点必须一致可以使用uuidgen生成;
group_replication_local_address 本机ip和端口;
group_replication_group_seeds 组的成员和端口;
group_replication_consistency = BEFORE_ON_PRIMARY_FAILOVER # 当Primary挂了的时候,备选Primary只有把事务全部执行完毕,才提供客户端读写操作;
group_replication_flow_control_mode = 'DISABLED' # 关闭流控,避免业务高峰触发限流。
2. 安装组复制插件及创建用户
各个节点安装mgr插件及创建用户:
set sql_log_bin=0;
set global super_read_only=0;
set global read_only=0;
create user 'rplmgr'@'192.168.79.1_' identified WITH mysql_native_password by 'Rep&%set123';
grant replication slave on *.* to 'rplmgr'@'%';
FLUSH PRIVILEGES;
install plugin group_replication soname 'group_replication.so';
show plugins;
3. 第一个节点加入MGR
change master to master_user='rplmgr', master_password='Rep&%set123' for channel 'group_replication_recovery';
SET GLOBAL group_replication_bootstrap_group=ON;
start group_replication;
SET persist group_replication_bootstrap_group=off;
SELECT * FROM performance_schema.replication_group_members;
select @@read_only,@@super_read_only;

4. 其余节点加入MGR
change master to master_user='rplmgr', master_password='Rep&%set123' for channel 'group_replication_recovery';
start group_replication;
SET persist group_replication_bootstrap_group=off;
SELECT * FROM performance_schema.replication_group_members;
select @@read_only,@@super_read_only;
第二节点加入:

第三节点加入:

5. 简单测试数据同步
MGR当前运行在单主模式下,简单测试数据同步:
在主节点创建测试数据:
create database test;
use test;
create table t1(id int not null, name varchar(32), primary key(id));
insert into t1(id, name) values(,'张三');
在其余节点验证数据:

6. 手工切换主节点
手工将主节点切换到mgr03节点:

7. 切换到多主模式

8. 切换到单主模式

也可以指定主节点:

9. 其它补充
如果是已有的系统改造为MGR架构,需要检查是否满足相关条件。
1)检查非INNODB表
SELECT table_name
,table_schema
,engine
FROM information_schema.tables
WHERE engine != 'innodb'
AND table_schema NOT IN ('mysql', 'information_schema', 'performance_schema');
如存在,许改造为innodb引擎表。
2)检查无主键或者唯一约束的表
SELECT concat(T1.TABLE_SCHEMA,".",T1.TABLE_NAME)
FROM INFORMATION_SCHEMA.COLUMNS T1
JOIN INFORMATION_SCHEMA.TABLES T2 ON T1.TABLE_SCHEMA=T2.TABLE_SCHEMA
AND T1.TABLE_NAME=T2.TABLE_NAME
WHERE T1.TABLE_SCHEMA NOT IN ('SYS',
'MYSQL',
'INFORMATION_SCHEMA',
'PERFORMANCE_SCHEMA')
AND T2.TABLE_TYPE='BASE TABLE'
GROUP BY T1.TABLE_SCHEMA,
T1.TABLE_NAME HAVING group_concat(COLUMN_KEY) NOT REGEXP 'PRI|UNI';
如存在需要改造:添加主键或唯一约束。

本文作者:张雷员(上海新炬王翦团队)
本文来源:“IT那活儿”公众号





