前言
MySQL Group Replication,简称MGR,是MySQL官方于2016年推出的一个全新的高可用解决方案,采用Paxos分布式一致性协议作为高可用和一致性解决方案。在MGR之前的高可用方案,本质上都是主从架构,多主发生脑裂时可能会导致双写问题,这在金融领域是不可忍受的,因此为了避免脑裂,大多数采用的还是单写。而MGR在多写模式下支持集群中的所有节点都可以写入,并保证一致性。
特点
- 支持多节点并发执行事务,并且保证副本之间数据一致。
- 自动事务冲突检测。
- 数据强一致性保障
- 容错性高。只要没有超过半数的节点故障就不影响集群整体可用性。
服务模式
MGR支持单主模式和多主模式,单主模式下只有一个节点负责写,但可以从任意节点读取。多主模式就是多写模式,写操作会下发到组内所有节点,组内所有节点同时可读可写。根据配置文件的参数 group_replication_single_primary_mode
确定是运行在单主模式还是多主模式。
单主模式下,如果主节点故障,MGR会自动选举出一个新的主节点,并设置为可写,其它从节点将指向这个新主节点。但是主节点漂移后,MGR并不会将客户端请求转移到新节点,这需要应用层或者中间件去解决。
多主模式不支持SERIALIZABLE串行隔离级、不完全支持级联外键约束、不完全支持并行执行ddl
注意事项
- MGR只支持InnoDB存储引擎,并且表中必须有显式主键
部署
环境
- 系统版本:centos 7
- docker版本:19.03
- mysql版本:8.0.22
- 架构:单机启动三个MySQL容器,MGR模式为单主模式
相关参数
# 单主模式还是多主模式,ON表示单主,OFF表示多主 group_replication_single_primary_mode
配置文件(docker环境)
[mysqld] pid-file = /var/run/mysqld/mysqld.pid socket = /var/run/mysqld/mysqld.sock datadir = /var/lib/mysql log-error=/var/lib/mysql/error.log # 监听端口,建议docker映射时对等映射 port=4306 secure-file-priv=NULL #skip-host-cache #skip-name-resolve character_set_server = utf8mb4 max_connections=5000 # 大小写不敏感 lower_case_table_names = 1 max_user_connections=3000 max_allowed_packet=32M sql_mode=STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,NO_ENGINE_SUBSTITUTION,ERROR_FOR_DIVISION_BY_ZERO # 事务隔离级别 transaction_isolation=READ-COMMITTED wait_timeout=300 default-time_zone='+8:00' # 每台主机server-id必须不一样 server_id=100 # binlog自动删除5天前的 binlog_expire_logs_seconds=432000 # MGR中binlog格式必须为row binlog-format=row # MGR要求binlog校验规则为NONE binlog_checksum=NONE # MGR要求把主从复制信息记录到表中 master_info_repository=TABLE relay_log_info_repository=TABLE # 将从节点从主节点收到的更新记录记入到从节点自己的二进制日志文件中 log-slave-updates=on # 禁止非innodb的存储引擎 disabled_storage_engines="MyISAM,BLACKHOLE,FEDERATED,ARCHIVE,MEMORY" # MGR模式下gtid必须开启 gtid-mode=on enforce-gtid-consistency=on # 必须为每个事务收集写集合,使用XXHASH算法将其编码为散列 transaction_write_set_extraction=XXHASH64 # 载入mgr插件 plugin_load_add='group_replication.so' # mgr名字,集群中唯一,集群中其他节点该参数应保持一致 group_replication_group_name="7119d536-04c4-11ed-9adf-0242ac120002" # 关闭重启MySQL时自动打开MGR,避免故障恢复时出现特殊情况影响数据准确性 group_replication_start_on_boot=off group_replication_bootstrap_group=off # 当前节点的ip和集群通信端口号 group_replication_local_address="mgr1:43061" # 其它节点的ip和集群通信端口号 group_replication_group_seeds= "mgr1:43061,mgr2:43071,mgr3:43081" # 服务模式 group_replication_single_primary_mode=on # 密码策略 default_authentication_plugin=mysql_native_password innodb_buffer_pool_size=256M [mysql] default-character-set = utf8mb4 #character-set-server=utf8 [mysql.server] default-character-set = utf8mb4 #character-set-server=utf8 [mysqld_safe] default-character-set = utf8mb4 #character-set-server=utf8 [client] default-character-set = utf8mb4 #character-set-server=utf8 # Custom config should go here !includedir /etc/mysql/conf.d/
三节点的配置文件内容只有port
、server_id
和group_replication_local_address
不一样。
由于MySQL 8.0.18修改了插件加载策略,所以docker安装MySQL的时候,要把mgr相关的参数先注释掉。也就是把 plugin_load_add
、group_replication_group_name
、group_replication_start_on_boot
、group_replication_start_on_boot
、group_replication_local_address
、group_replication_group_seeds
、group_replication_single_primary_mode
这几个参数暂时先注释掉,初始化完成后再取消注释。
准备
mkdir -p /home/apps/mgr{1..3}/{conf,data} # 将配置文件分别拷贝到conf目录,注意根据实际情况修改参数
使用docker-compose创建容器
- docker-compose.yaml示例。
8.0.22有点bug,用端口映射的方式在启动mgr的时候会报错找不到网卡,所以网络模式用的host。另外hosts文件也要映射进去,根据ip启动mgr时候可能会找不到其它节点。hosts文件中写主机名和ip的映射关系。
version: "3" services: mgr1: image: mysql:8.0.22 container_name: mgr1 network_mode: "host" volumes: - /home/apps/mgr1/data:/var/lib/mysql - /home/apps/mgr1/conf/my.cnf:/etc/mysql/my.cnf - /etc/localtime:/etc/localtime:ro - /etc/hosts:/etc/hosts:ro ports: - 4306:4306 - 43061:43061 environment: - MYSQL_ROOT_PASSWORD=123456 mgr2: image: mysql:8.0.22 container_name: mgr2 network_mode: "host" volumes: - /home/apps/mgr2/data:/var/lib/mysql - /home/apps/mgr2/conf/my.cnf:/etc/mysql/my.cnf - /etc/localtime:/etc/localtime:ro - /etc/hosts:/etc/hosts:ro ports: - 4307:4307 - 43071:43071 environment: - MYSQL_ROOT_PASSWORD=123456 mgr3: image: mysql:8.0.22 container_name: mgr3 network_mode: "host" volumes: - /home/apps/mgr3/data:/var/lib/mysql - /home/apps/mgr3/conf/my.cnf:/etc/mysql/my.cnf - /etc/localtime:/etc/localtime:ro - /etc/hosts:/etc/hosts:ro ports: - 4308:4308 - 43081:43081 environment: - MYSQL_ROOT_PASSWORD=123456
- 先注释掉
my.cnf
中关于mgr的参数,创建容器并初始化
docker-compose up -d
- 启动完成后,随便进一个容器内的mysql控制台,看看MySQL运行是否正常,确认正常后退回到宿主机。
- 停止docker容器,并恢复配置文件中mgr相关的参数
docker-compose stop # 修改三节点的my.cnf docker-compose start
- 登录docker中的MySQL控制台,查看mgr插件是否已加载:
show plugins;
创建用户
三个节点创建用户用于同步,需要注意的是,创建用户和修改密码的操作需要关闭binlog,执行后再打开。
set sql_log_bin=0; reset master; create user rpl_user@'%' identified by '123456'; GRANT REPLICATION SLAVE ON *.* TO rpl_user@'%'; GRANT CONNECTION_ADMIN ON *.* TO rpl_user@'%'; GRANT BACKUP_ADMIN ON *.* TO rpl_user@'%'; -- 8.0.27版本需要授予GROUP_REPLICATION_STREAM权限 -- GRANT GROUP_REPLICATION_STREAM ON *.* TO rpl_user@'%'; -- grant replication slave on *.* to rpl_user@'%' identified by '123456'; flush privileges; set sql_log_bin=1;
创建同步规则认证信息
每个节点都要配置
change master to master_user='rpl_user',master_password='123456' for channel 'group_replication_recovery'; -- MySQL 8.0.23后命令会不一样 CHANGE REPLICATION SOURCE TO SOURCE_USER='rpl_user', SOURCE_PASSWORD='123456' FOR CHANNEL 'group_replication_recovery';
安装插件
可以先执行show plugins;
查看group_replication
是否已加载,如果没有则手动加载
INSTALL PLUGIN group_replication SONAME 'group_replication.so';
启动mgr
启动mgr
-- 先在主节点初始化 SET GLOBAL group_replication_bootstrap_group=ON; -- 8.0.21之前 START GROUP_REPLICATION; -- 8.0.21及其之后也可以换一种方式 -- START GROUP_REPLICATION USER='rpl_user', PASSWORD='123456'; -- 关闭group_replication_bootstrap_group SET GLOBAL group_replication_bootstrap_group=OFF; -- 主节点成功执行后,在其它节点执行 START GROUP_REPLICATION;
查看mgr集群状态
SELECT * FROM performance_schema.replication_group_members;
测试
建库建表测试
参考
- 宋立恒- MySQL性能优化和高可用架构实践
- 官方在线文档