1 What's Group Replication
- 主库执行完事务后,同步binlog给从库,从库ack反馈接收到binlog,主库提交commit,反馈给客户端,释放会话;
- 主库执行完事务后,主库提交commit ,同步binlog给从库,从库ack反馈接收到binlog,反馈给客户端,释放会话;
- 写操作集中在MASTER服务器上;
- MASTER宕机后,需要人为选择新主并重新给其他的slave端执行change master(可自行写第三方工具实现,但是mysql的复制就是没提供,所以也算是弊端)
- 多主,在同一个group里边的所有实例,每一个实例可以执行写操作,也就是每个实例都执行Read-Write
- 注意一点,多主情况下,当执行一个事务时,需要确保同个组内的每个实例都认可这个事务无冲突异常,才可以commit,如果设置的是单主,其他实例ReadOnly,则不需要进行上面的判断
- 多主情况下,事务并发冲突问题就凸显出来了,如何避免呢?数据库内部有一个认证程序,当不同实例并发对同一行发起修改,在同个组内广播认可时,会出现并发冲突,那么会按照先执行的提交,后执行的回滚
- 弹性,同个Group Replication中,节点的加入或者移除都是自动调整;如果新加入一个节点,该节点会自动从Group的其他节点同步数据,直到与其他节点一致;如果移除一个节点,那么剩下的实例会自动更新,不再向这个节点广播事务操作,当然,这里要注意,假设一个Group的节点有n个(max(n)=9,同个Group最多节点数为9),移除或者宕机的节点数应该小于等于 floor((n-1)/2) ,注意是向下取整;如果是单主模式,宕机的是单主,则人为选择新主后,其他节点也会自动从新主同步数据。
- 更高性能的同步机制
2 配置要求与限制
2.1 数据库要求
2.1.1 innodb引擎
2.1.2 主键
2.1.3 隔离级别
2.1.4 外键
2.1.5 IPv4网络,网络性能稳定延迟小带宽充足
2.2 安装mysql_replication引擎前提
- master info and relay log info repositories
- master_info_repository
- set global master_info_repository ='table';
- relay_log_info_repository
- set global relay_log_info_repository=‘table';
- 如果不设置会报错,报错信息如下
- [ERROR] For the creation of replication channels the master info and relay log info repositories must be set to TABLE
- master_info_repository
- binlog_checksum
- binlog的校验方式应该设置为none
- 如果不设置,报错性能如下
- [ERROR] Plugin group_replication reported: 'binlog_checksum should be NONE for Group Replication'
2.3 其他参数要求
- binary log设置
- 需要启动记录binary log,任何复制都需要使用到二进制内容
- 在配置文件中添加 log-bin = [binlog存储路径及命名方式]
- 例子: log-bin = /data/mysql/mysql3310/logs/bin_log
- log-slave-updates设置
- 默认情况下,主库同步到从库执行的内容,是不产生binlog日志的,一般开启该参数是为了满足 多级复制,比如 A->B->C(A是B的主库,B是C的主库),那么这个时候B就需要开启这个参数记录从A同步到B上面的所有操作到binary log中,这样才能完整的同步到C上。
- 而在MGR中,组中的server需要记录从组接收和应用的所有事务,因为恢复的时候,是依赖域各个组的二进制日志内容的。
- 那么这个时候,可能就有个疑问,在多主模式下,假设实例A ,B , C三台中,每个实例修改的内容都记录到binary log中,再同步给其他组成员,那在B上执行事务 tranb : update了一行数据,tranb提交后同步到 A跟C,各自执行后,由于启动了log-slave-updates设置,A跟C也生成了binary log,那么这些日志如果再同步回B,再执行一遍,不就可能出现问题了吗?实际上这个担忧是多余的,在MGR中,启动了GTID模式,会检查GTID EXCUTED集合,如果是已经执行的,则不会再次执行。
- binary log格式
- MGR依赖以及与行复制格式
- binlog_format=row
- GTID模式启动
- 组复制使用全局事务标识符来记录哪些事务已在所有server实例上提交,从而判断哪些是已提交事务哪些是冲突事务,避免重复执行及数据不一致
- gtid_mode=ON
- transaction_write_set_extraction
- 这个神奇的参数5.7.6版本引入,用于定义一个记录事务的算法,这个算法使用hash标识来记录事务。如果使用MGR,那么这个hash值需要用于分布式冲突检测何处理,在64位的系统,官网建议设置该参数使用 XXHASH64 算法。
- transaction_write_set_extraction ='XXHASH64'
- 官网解释:Defines the algorithm used to generate a hash identifying the writes associated with a transaction. If you are using Group Replication, the hash value is used for distributed conflict detection and handling. On 64-bit systems running Group Replication, we recommend setting this to XXHASH64 in order to avoid unnecessary hash collisions which result in certification failures and the roll back of user transactions
3 搭建Mysql Group Replication
- 注意通讯端口号的配置,它用于组成员之间的通讯使用
- 请确定当前MySQL版本为5.7.17或者之后版本
- 每个实例的serverid必须是唯一标识,建议使用ip末端+端口描述
实例名
|
A
|
B
| C |
IP
|
192.168.9.242
|
192.168.9.242
|
192.168.9.244
|
实例端口号
|
3310
|
3320
|
3340
|
Server-ID |
2423310
|
2423320
|
2443340
|
通讯端口号
|
24201
|
24202
|
24404
|
MySQL Versoin
|
5.7.17
|
5.7.17
|
5.7.17
|
MGR参数配置方式
|
修改配置文件
|
修改配置文件
|
修改配置文件
|
3.1 单主模式(group_replication_single_primary_mode =ON)
3.1.1 主机名修改
1 #查看当前主机名
2 hostname
3 4 #修改主机名 5 hostname sutest242 6 7 #进入vim /etc/hosts 8 #添加记录,不要修改默认的 127.0.0.1跟::1的记录,其他的系统服务会使用到的 9 127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4 10 ::1 localhost localhost.localdomain localhost6 localhost6.localdomain6 11 192.168.9.242 sutest242 12 192.168.9.244 sutest244
3.1.2 设置环境变量
1 #动态配置:
2 set global transaction_write_set_extraction='XXHASH64'; 3 set global group_replication_start_on_boot=OFF; 4 set global group_replication_bootstrap_group = OFF ; 5 set global group_replication_group_name= '9ac06b4e-13aa-11e7-a62e-5254004347f9'; #某个UUID 6 set global group_replication_local_address='192.168.9.242:24201'; 7 set global group_replication_group_seeds ='192.168.9.242:24201,192.168.9.242:24202,192.168.9.242:24401'; 8 set global group_replication_ip_whitelist = '127.0.0.1/8,192.168.9.0/24'; 9 set global group_replication_single_primary_mode=True; 10 set global group_replication_enforce_update_everywhere_checks=False; 11 12 #cnf文件配置: 13 server-id=12001 14 transaction_write_set_extraction = XXHASH64 15 loose-group_replication_group_name = '9ac06b4e-13aa-11e7-a62e-5254004347f9' 16 loose-group_replication_ip_whitelist = '127.0.0.1/8,192.168.9.0/24' 17 loose-group_replication_start_on_boot = OFF 18 loose-group_replication_local_address = '192.168.9.242:24201' 19 loose-group_replication_group_seeds = '192.168.9.242:24201,192.168.9.242:24202,192.168.9.242:24401' 20 loose-group_replication_bootstrap_group = OFF 21 loose-group_replication_single_primary_mode = true 22 loose-group_replication_enforce_update_everywhere_checks = false
3.1.3 建立复制账号
3.1.4 安装引擎
3.1.5 配置Group
1 #实例A
2 #1 查看当前的group replication相关参数是否配置有误 3 show global variables like 'group%'; 4 5 #2 启动 group_replication_bootstrap_group 6 SET GLOBAL group_replication_bootstrap_group=ON; 7 8 #3 配置MGR 9 CHANGE MASTER TO MASTER_USER='repl', MASTER_PASSWORD='replforslave' FOR CHANNEL 'group_replication_recovery'; 10 11 #4 启动MGR 12 start group_replication; 13 14 #5 查看Error log,截图如下 15 #error log如果有问题,拉到本文末端,对应找错误,如果没有解决,请google或者留言 16 17 #6 关闭 group_replication_bootstrap_group 18 SET GLOBAL group_replication_bootstrap_group=OFF;
#实例A
mysql> create database mgr; Query OK, 1 row affected (0.01 sec) mysql> use mgr Database changed mysql> create table tb1(id int primary key auto_increment not null,name varchar(100)); Query OK, 0 rows affected (0.10 sec) mysql> insert into tb1(name) select @@server_id; Query OK, 1 row affected (0.09 sec) Records: 1 Duplicates: 0 Warnings: 0 mysql> insert into tb1(name) select @@server_id; Query OK, 1 row affected (0.00 sec) Records: 1 Duplicates: 0 Warnings: 0 mysql> insert into tb1(name) select @@server_id; Query OK, 1 row affected (0.01 sec) Records: 1 Duplicates: 0 Warnings: 0 mysql> insert into tb1(name) select @@server_id; Query OK, 1 row affected (0.00 sec) Records: 1 Duplicates: 0 Warnings: 0 mysql> select * from tb1; +----+---------+ | id | name | +----+---------+ | 6 | 2423310 | | 13 | 2423310 | | 20 | 2423310 | | 27 | 2423310 | +----+---------+ 4 rows in set (0.00 sec) mysql> show master status; +----------------+----------+--------------+------------------+------------------------------------------+ | File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set | +----------------+----------+--------------+------------------+------------------------------------------+ | bin_log.000002 | 1795 | | | 9ac06b4e-13aa-11e7-a62e-5254004347f9:1-7 | +----------------+----------+--------------+------------------+------------------------------------------+ 1 row in set (0.00 sec)
1 #实例B
2 #1 查看当前的group replication相关参数是否配置有误 3 show global variables like 'group%'; 4 5 #2 配置MGR 6 CHANGE MASTER TO MASTER_USER='repl', MASTER_PASSWORD='replforslave' FOR CHANNEL 'group_replication_recovery'; 7 8 #3 启动MGR 9 start group_replication; 10 11 #4 查看Error log,截图如下 12 #error log如果有问题,拉到本文末端,对应找错误,如果没有解决,请google或者留言
1 #实例A
2 mysql> use mgr 3 Database changed 4 mysql> create table tb2(id int auto_increment primary key not null,namea varchar(8000),nameb varchar(8000)); 5 Query OK, 0 rows affected (0.03 sec) 6 7 mysql> insert into tb2(namea,nameb) select repeat('a',8000),repeat('b',8000); 8 Query OK, 1 row affected (0.02 sec) 9 Records: 1 Duplicates: 0 Warnings: 0 10 11 #insert 自行操作,看试验需要,本次需要大量数据来recovery,所以后面采用 insert into tb2 .. select .. from tb2 方式造数据 2w+行
1 #实例C
2 #1 查看当前的group replication相关参数是否配置有误 3 show global variables like 'group%'; 4 5 #2 配置MGR 6 CHANGE MASTER TO MASTER_USER='repl', MASTER_PASSWORD='replforslave' FOR CHANNEL 'group_replication_recovery'; 7 8 #3 启动MGR 9 start group_replication; 10 11 #4 查看Error log,截图如下 12 #error log如果有问题,拉到本文末端,对应找错误,如果没有解决,请google或者留言
在搭建的过程中,也理清了两个重要通道的使用情况:
- group_replication_applier 通道 提供组内成员向 MASTER 实时同步binlog日志使用,这个通道内IO_thread拉取到的日志存放在 *_apaplier.* 系列文件中,再通过SQL_Thread应用到组内的各个SERVER上。
- group_replication_recovery 通道 提供 首次加入GROUP或者重新加入GROUP时恢复数据使用,这个通道内 IO_thread拉取到的日志存放在 *_recovery.* 系列文件中,再通过SQL_Thread应用到组内的各个SERVER上,应用结束后,删除所有 *_recovery.* 系列文件 ,重新建立新的 *_recovery.* 系列文件。
3.2 多主模式(group_replication_single_primary_mode =OFF)
# 动态修复方式
set global group_replication_single_primary_mode=OFF; # 配置文件修改方式 loose-group_replication_single_primary_mode = OFF
3.2.1 业务端连接IP处理
3.2.2 GROUP内成员逐个依次主动退出GROUP
1 #实例A
2 stop group_replication;
3 4 #检查实例B,C的error log,发现实例A主动退出,group成员删除实例A
1 #实例B
2 stop group_replication;
3 4 #检查实例B,C的error log,发现实例A主动退出,group成员删除实例A
#实例c
stop group_replication;
3.2.3 关闭 group_replication_single_primary_mode参数
#动态修改
#实例A
set global group_replication_single_primary_mode =OFF #实例B set global group_replication_single_primary_mode =OFF #实例C set global group_replication_single_primary_mode =OFF #配置文件添加 #实例A的cnf文件中修改 loose-group_replication_single_primary_mode = OFF #实例B的cnf文件中修改 loose-group_replication_single_primary_mode = OFF #实例C的cnf文件中修改 loose-group_replication_single_primary_mode = OFF
#实例A
mysql> create table tb4 like tb2; Query OK, 0 rows affected (0.18 sec) mysql> insert into tb4 select * from tb2; Query OK, 20480 rows affected (33.13 sec) Records: 20480 Duplicates: 0 Warnings: 0
3.2.4 逐个启动GROUP内的SERVER
#实例A
#需要启动 group_replication_bootstrap_group 引导组,启动后需要关闭,防止脑裂
mysql> set global group_replication_bootstrap_group=ON; Query OK, 0 rows affected (0.00 sec) mysql> CHANGE MASTER TO MASTER_USER='repl', MASTER_PASSWORD='replforslave' FOR CHANNEL 'group_replication_recovery'; Query OK, 0 rows affected, 2 warnings (0.02 sec) mysql> START GROUP_REPLICATION; Query OK, 0 rows affected (1.16 sec) mysql> set global group_replication_bootstrap_group=Off; Query OK, 0 rows affected (0.00 sec) #实例B mysql> CHANGE MASTER TO MASTER_USER='repl', MASTER_PASSWORD='replforslave' FOR CHANNEL 'group_replication_recovery'; Query OK, 0 rows affected, 2 warnings (0.04 sec) mysql> start group_replication; Query OK, 0 rows affected (4.31 sec) #实例C mysql> CHANGE MASTER TO MASTER_USER='repl', MASTER_PASSWORD='replforslave' FOR CHANNEL 'group_replication_recovery'; Query OK, 0 rows affected, 2 warnings (0.07 sec) mysql> start group_replication; Query OK, 0 rows affected (3.83 sec)
3.2.5 检查现在GROUP情况
mysql> select * from performance_schema.replication_group_members; +---------------------------+--------------------------------------+-------------+-------------+--------------+ | CHANNEL_NAME | MEMBER_ID | MEMBER_HOST | MEMBER_PORT | MEMBER_STATE | +---------------------------+--------------------------------------+-------------+-------------+--------------+ | group_replication_applier | 2ec0fecd-16a2-11e7-97e1-52540005b8e1 | sutest244 | 3340 | ONLINE | | group_replication_applier | 94e39808-15ed-11e7-a7cf-52540005b8e2 | sutest242 | 3310 | ONLINE | | group_replication_applier | 9b78d231-15ed-11e7-a82a-52540005b8e2 | sutest242 | 3320 | ONLINE | +---------------------------+--------------------------------------+-------------+-------------+--------------+ 3 rows in set (0.21 sec) mysql> select * from performance_schema.global_status where variable_name like '%group%'; +----------------------------------+----------------+ | VARIABLE_NAME | VARIABLE_VALUE | +----------------------------------+----------------+ | group_replication_primary_member | | +----------------------------------+----------------+ 1 row in set (0.35 sec) mysql> show global variables like 'group_replication_single_primary_mode'; +---------------------------------------+-------+ | Variable_name | Value | +---------------------------------------+-------+ | group_replication_single_primary_mode | OFF | +---------------------------------------+-------+ 1 row in set (0.33 sec) mysql> show global variables like 'super%'; +-----------------+-------+ | Variable_name | Value | +-----------------+-------+ | super_read_only | OFF | +-----------------+-------+ 1 row in set (1.20 sec)
4 管理维护
id | table_schema | table_name | type | description |
1 | performance_schema | replication_group_members | 重要,常用 | 查看GROUP成员。 |
2 | performance_schema | replication_group_member_stats | 重要,常用 | 当前SERVER在GROUP中的同步情况,查看applier通道的同步情况。 |
3 | performance_schema | replication_connection_stats | 重要,常用 | 当前server中各个通道的使用情况,applier通道是一定有显示,recovery通道看是否使用过,如果有则显示,没有则不显示。 |
4 | performance_schema | replication_applier_stats | 重要,常用 | 当前server中各个通道是否启用。 |
5 | performance_schema | global_status | 重要,常用 | 单主模式下,可以查看当前主库是哪个。 |
6 | performance_schema | replication_applier_configuration | 不常用,了解即可 | |
7 | performance_schema | replication_applier_status_by_coordinator | 不常用,了解即可 | |
8 | performance_schema | replication_applier_status_by_worker | 不常用,了解即可 | |
9 | performance_schema | replication_connection_configuration | 不常用,了解即可 | |
10 | mysql | slave_master_info | 重要,不常用 | 设置了master_info_repository=TABLE,所以master的相关信息会存储在这个表格。 如果使用GROUP中的SERVER备份数据库,恢复到时候,注意要清理这个表格。 |
11 | mysql | slave_relay_log_info | 重要,不常用 | 设置了relay_log_info_repository=TABLE,所以master的相关信息会存储在这个表格。 如果使用GROUP中的SERVER备份数据库,恢复到时候,注意要清理这个表格。 |
4.1 查看GROUP中的成员有哪些
4.2 单主模式下主库是哪个
4.3 检查数据库是否正常提供读写服务
4.4 检查数据库是否复制出现问题
5 故障模拟及处理
节选测试过程的图,跟之前配置的GROUP有些不一致,理解注重思路即可,部分测试细节没有再次描述。
5.1 单主模式
5.1.1 主库宕机,如何自动选择新主库?各个实例之间的super_read_only模式如何切换?
select * from performance_schema.replication_group_members;
select * from performance_schema.global_status where VARIABLE_NAME='group_replication_primary_member'; show global variables like 'server_uuid'; show global variables like 'super%'; select * from performance_schema.replication_connection_status; select * from performance_schema.replication_applier_status;
模拟group中,有三个实例,端口分别为 3320,3330,3340,用简称来 m3320、m3330、m3340来分别描述。
5.1.2 主库宕机后,恢复,重新加入group
CHANGE MASTER TO MASTER_USER='repl', MASTER_PASSWORD='replforslave' FOR CHANNEL 'group_replication_recovery'; START GROUP_REPLICATION;
5.1.3 从库宕机1台,影响情况
5.1.4 从库宕机2台,影响情况
5.1.5 新增从库:innobackupex新增(这个需要留意)
1 innobackupex --datadir=/data/mysql/mysql3320/data/ --user=root --password=ycf.com --no-timestamp --socket=/tmp/mysql3320.sock /data/backup3320
2 innobackupex --apply-log /data/backup3320
1 truncate table mysql.slave_master_info
2 truncate table mysql.slave_relay_log_info 3 4 rm -rf applier系列文件 5 rm -rf recovery系列文件
RESET MASTER;
SET @@GLOBAL.GTID_PURGED='9ac06b4e-13aa-11e7-a62e-5254004347f9:1-10';
CHANGE MASTER TO MASTER_USER='repl', MASTER_PASSWORD='replforslave' FOR CHANNEL 'group_replication_recovery'; START GROUP_REPLICATION;
5.1.6 新增从库:mysqldump新增(这个需要留意)
SET @@GLOBAL.GTID_PURGED='9ac06b4e-13aa-11e7-a62e-5254004347f9:1-18'; #看GTID集合是否一致 CHANGE MASTER TO MASTER_USER='repl', MASTER_PASSWORD='replforslave' FOR CHANNEL 'group_replication_recovery'; START GROUP_REPLICATION;
5.2 多主模式
5.2.1 单主模式切换多主模式
5.2.2 宕机一台整体影响
5.2.3 宕机后重新加入
5.2.4 宕机超过合理个数,整体影响(非一个个慢慢宕机,而是一口气宕机超过合理个数)
5.2.5 新增DB:innobackupex新增
- 备份后执行apply log
- 新建实例,添加plugins引擎
- 替换数据目录
- 启动数据库
- 清理relay-log文件,清理slave_master_info跟slave_relay_log_info信息
- 查看当前的GTID序号是否与 xtrabackup_binlog_info记录一致,如果不一致,执行 set gtid_purged
- 重启数据库服务
- 检查group replication配置是否有误
- change master
- start group_replication
#部分参考SQL
SET @@GLOBAL.GTID_PURGED='9ac06b4e-13aa-11e7-a62e-5254004347f9:1-26:1000004'; CHANGE MASTER TO MASTER_USER='repl', MASTER_PASSWORD='replforslave' FOR CHANNEL 'group_replication_recovery'; START GROUP_REPLICATION;
5.2.6 新增DB:mysqldump新增
- 新建实例,添加plugins引擎
- source 备份文件
- 清理relay-log文件,清理slave_master_info跟slave_relay_log_info信息
- 查看当前的GTID序号是否与备份文件前面记录一致,如果不一致,执行 set gtid_purged
- 检查group replication配置是否有误
- change master
- start group_replication
6 问题记录
1 ip间隔是 逗号
2 不要有分号,本人就这么笨的开始!
3 port是使用端口号 ,非实例端口号
4 [ERROR] Plugin group_replication reported: 'This member has more executed transactions than those present in the group. Local transactions: 32538cbf-12fc-11e7-af43-5254004347f9:1-5 > Group transactions: 2236bd6b-12fc-11e7-a706-5254004347f9:1-16
[ERROR] Plugin group_replication reported: 'The member contains transactions not present in the group. The member will now exit the group.'
[Note] Plugin group_replication reported: 'To force this member into the group you can use the group_replication_allow_local_disjoint_gtids_join option'
- 解决
- set global group_replication_allow_local_disjoint_gtids_join=ON;(但是实际上这种方法治标不治本)
- 建议还是在搭建group_replication的时候,在start group_replication之前,reset master,重置所有binary log,这样就不会出现各个实例之间的日志超前影响;但是这里要考虑是否影响到旧主从。
5 [ERROR] Plugin group_replication reported: 'Table te does not have any PRIMARY KEY. This is not compatible with Group Replication'
表格需要添加主键
6 mysql> insert into ct(id,name) select 2,'b'; ERROR 1290 (HY000): The MySQL server is running with the --super-read-only option so it cannot execute this statement
只读模式下,不提供写服务。
7 [ERROR] Plugin group_replication reported: 'Transaction cannot be executed while Group Replication is on ERROR state. Check for errors and restart the plugin' 2017-03-29T15:46:13.619141Z 31 [ERROR] Run function 'before_commit' in plugin 'group_replication' failed
GROUP出错了,是否是重复执行冲突了,好好处理下