[MySQL Reference Manual]17 Group Replication
17 Group Replication
17.2.1 Group Replication部署单主模式
17.2.1.1 部署Group Replication实例
17.2.1.2 为一个实例配置Group Replication
17.3.1 Replication_group_member_stats
17.3.2 Replication_group_members
17.3.3 Replication_connection_status
17.3.4 Replication_applier_status
17.3.5 Group Replication Server States
17.4.3.2 Unblocking a Partition
17.9.3 Data Manipulation Statements
17.9.4 Data Definition Statements
17.5.9.2 Recovering From a Point-in-time
17.1 Group Replication后台
最常用创建容错系统是使用手段来冗余组件,也就是说组件可以被删除,但是系统还是正常运行。复制的数据库必须面临的一个问题,他们需要维护和管理多个实例,还有服务组合在一起创建,把一切其他传统分布式系统组合的问题也必须解决。
最主要的问题是抱着数据库和数据的复制在几个服务合作下,逻辑是一致的并且是简单的。也就是说,多个服务同意系统和数据的状态,并且同意系统前进时的每个修改。就是服务在每个数据库的传输的状态都必须同意,所有的处理就好像在一个数据库或者之后会覆盖的其他数据库到相同的状态。
MySQL Group Replication提供了分布式复制,使用server之间的强连接,如果服务在相同的group,那么久会自动连接上。Group可以是单主,也可以是多主的。
有一个编译好的服务,在任意时间点,可以看group的一致性和可用性。服务可以加入,离开group,并且view会有相应的更新。有时候服务会异常离开group,那么错误诊断机制会发现并且通知组并且修改view,这些都是自动的。
对于事务提交,需要大多数同意。事务提交和回滚完成是由单独服务确定的,不是所有的服务决定。如果有一个network partition,那么就会导致分裂,成员不能相互通信,因此系统不能处理,知道问题被解决。当然也有内置的,自动的主分裂保护的机制。
17.1.1 Replication技术
17.1.1.1 主从复制
MySQL传统的主从复制。有一个主,多个从。主执行事务,提交然后发送到从,重新执行。是shared-nothing系统,所有的服务默认是full copy的。
17.1.1.2 Group Replication
Group Replication可以用于容错系统,是一组互相交互的服务。交互层提供了机制确保消息的原子性和消息的交互。
Group Replication实现了多主的复制。复制组由多个服务组成,每个服务都可以运行事务。读写的时候之后group认可之后才能提交。只读事务因为不需要和group交互,因此提交很快。也就是说关于写入事务,group需要决定事务是否提交,而不是原始的服务单独确定的。当原始服务准备提交,服务会自动广播。然后事务的全局顺序被建立。这个很重要,也就是说所有的服务在相同的事务顺序下,收到了相同的事务。这样也就保证了group的数据一致性。
当然不同的服务并发的执行事务也会有冲突。这种冲突出现在检查不同写入集合的并发事务。这个过程叫做certification 。如果2个并发事务在不同的服务上运行,更新了相同的行,那么就是发生冲突了。解决方法是提交顺序在前面的,另外一个就回滚。
17.1.2 Group Replication使用场景
略,具体看:
https://dev.mysql.com/doc/refman/5.7/en/group-replication-use-cases.html
17.1.3 Group Replication细节
17.1.3.1 错误发现
有一个错误发现机制,用来找出报告那个服务是静默的,然后假定为已经挂了。错误发现其实分布式服务用来提供服务的活动信息。之后group决定服务确实出错,那么剩下的group成员就会排除这个成员。
当服务静默,错误发现机制就会被触发。当服务A没有收到来自服务B的,而且超时就会触发。
如果服务被所有的成员隔离,并怀疑所有的node都是错误的。就不能被group保护,怀疑是无效的。当服务被怀疑,那么就不能再执行任何本地事务。
17.1.3.2 Group成员
MySQL Group Replication管理到Group成员服务,这个服务是内置的插件,定义了那个服务是在线的,可以投票的。在线的服务被称为view。因此每个group内的服务都有一个一样的view,表示那个服务是活动的。
所有服务需要统一的不单单是事务提交,还有当前的view。因此如果所有同意一个新的服务的加入,然后Group重新配置,加入这个服务,并且出发view的修改。当服务离开group的时候也会发生,然后group重排配置,并且出发view的修改。
当一个成员自觉的离开group,会先初始化Group的重新配置。然后出发一个过程,除了一开的服务之外,其他服务都要同意,如果成员是因为故障一开的,错误发现机制发现问题,并且发出重新配置的提议。需要所有的服务同意,如果不能同意那么group的配置就无法修改。也就是说管理员需要手工来修复。
17.1.3.3 错误容忍
Group Replication实现了Paxos分布式算法来提供服务的分布式服务。要求大多数的服务活动以达到大多数,来做个决定。直接影响了系统可以容忍的错误容错公司如下,服务器n,容错f:n = 2 x f + 1
也就是说,容忍一个错误那么group必须要有3个成员。因为就算有一个错了,还有2个,任然可以形成大多数来处理一些事情。如果另外一个也挂, 那么就剩下一个,不发形成大多数(大于半数)。
Group Size |
Majority |
Instant Failures Tolerated |
1 |
1 |
0 |
2 |
2 |
0 |
3 |
2 |
1 |
4 |
3 |
1 |
5 |
3 |
2 |
6 |
4 |
2 |
7 |
4 |
3 |
17.2 Getting Start
17.2.1 Group Replication部署单主模式
每个实例可以运行在单个机器上,可以在同一个机器上。
17.2.1.1 部署Group Replication实例
第一步不是三个实例。Group Replication是MySQL内部的插件,MySQL 5.7.17之后版本都开始有。
mkdir data
mysql-5.7/bin/mysqld --initialize-insecure --basedir=$PWD/mysql-5.7 --datadir=$PWD/data/s1
mysql-5.7/bin/mysqld --initialize-insecure --basedir=$PWD/mysql-5.7 --datadir=$PWD/data/s2
mysql-5.7/bin/mysqld --initialize-insecure --basedir=$PWD/mysql-5.7 --datadir=$PWD/data/s3
17.2.1.2 为一个实例配置Group Replication
配置服务的基本配置:
[mysqld]
# server configuration
datadir=<full_path_to_data>/data/s1
basedir=<full_path_to_bin>/mysql-5.7/
port=24801
socket=<full_path_to_sock_dir>/s1.sock
配置复制相关,并启动GTID
server_id=1
gtid_mode=ON
enforce_gtid_consistency=ON
master_info_repository=TABLE
relay_log_info_repository=TABLE
binlog_checksum=NONE
log_slave_updates=ON
log_bin=binlog
binlog_format=ROW
Group Replication配置
transaction_write_set_extraction=XXHASH64
loose-group_replication_group_name="aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa"
loose-group_replication_start_on_boot=off
loose-group_replication_local_address= "127.0.0.1:24901"
loose-group_replication_group_seeds= "127.0.0.1:24901,127.0.0.1:24902,127.0.0.1:24903"
loose-group_replication_bootstrap_group= off
第一行:所有的写入的事务的write set使用XXHASH64进行编码。
第二行:要加入的group的名字
第三行:服务启动后,不自动启动
第四行:使用127.0.0.1,端口为24901,来接入group成员的连接。
第五行:当加入一个group时,需要连接的host,只需要连接一个,然后该阶段会要求group重新配置,允许服务器加入到group。当多个服务同时要求加入group,保证用的seed已经在group 中。
第六行:插件是否关联到group,这个参数很重要,必须只有一个服务使用,不然会出现主分裂的情况,就是不同的group有相同的Group名字。第一个服务实例online之后就禁用这个选项。
17.2.1.3 用户授权
Group Replication使用异步复制的协议,处理分布的恢复,来同步将要加入group的成员。分布的恢复处理依赖于复制通道,group_replication_recovery 用来在group成员之间做传输。因此需要一个复制用户和足够的权限,用户成员之间的恢复复制通道。
创建一个拥有REPLICATION_SLAVE权限的用户,但是这个过程不能被binlog捕获。
mysql> SET SQL_LOG_BIN=0;
Query OK, 0 rows affected (0,00 sec)
mysql> CREATE USER rpl_user@'%' IDENTIFIED BY 'rpl_pass';
Query OK, 0 rows affected (0,00 sec)
mysql> GRANT REPLICATION SLAVE ON *.* TO rpl_user@'%';
Query OK, 0 rows affected, 1 warning (0,00 sec)
mysql> FLUSH PRIVILEGES;
Query OK, 0 rows affected (0,00 sec)
mysql> SET SQL_LOG_BIN=1;
Query OK, 0 rows affected (0,00 sec)
配置好之后,使用change master to语句配置服务
mysql> CHANGE MASTER TO MASTER_USER='rpl_user', MASTER_PASSWORD='rpl_pass' \\
FOR CHANNEL 'group_replication_recovery';
Query OK, 0 rows affected, 2 warnings (0,01 sec)
分布式恢复的第一步就是把服务加入到Group中,如果账号和权限设置的不对那么无法运行恢复进程,最重要的是无法加入到group。类似的,如果成员不能正确的通过host识别其他成员那么恢复进程也会错误。可以通过performance_schema. replication_group_members查看host。可以使用report_host区别开来。
17.2.1.4 执行Group Replication
弄完上面的配置,并且启动后,连接到服务,执行一下命令:
INSTALL PLUGIN group_replication SONAME 'group_replication.so';
安装好之后可以通过show plugins查看,如果安装成功就会在返回中。
启动group,让s1关联group并且启动Group Replication。这个关联要单个服务器完成,并且只能启动一次。所以这个配置不能保存在配置文件中,如果保存了,下次启动会自动关联到第二个Group,并且名字是一样的。如果开关plugin,但是参数是ON的也会有这个问题。
SET GLOBAL group_replication_bootstrap_group=ON;
START GROUP_REPLICATION;
SET GLOBAL group_replication_bootstrap_group=OFF;
一旦start完成,就可以查到成员了:
mysql> SELECT * FROM performance_schema.replication_group_members;
+---------------------------+--------------------------------------+-------------+-------------+---------------+
| CHANNEL_NAME | MEMBER_ID | MEMBER_HOST | MEMBER_PORT | MEMBER_STATE |
+---------------------------+--------------------------------------+-------------+-------------+---------------+
| group_replication_applier | ce9be252-2b71-11e6-b8f4-00212844f856 | myhost | 24801 | ONLINE |
+---------------------------+--------------------------------------+-------------+-------------+---------------+
1 row in set (0,00 sec)
增加一些数据:
mysql> CREATE DATABASE test;
Query OK, 1 row affected (0,00 sec)
mysql> use test
Database changed
mysql> CREATE TABLE t1 (c1 INT PRIMARY KEY, c2 TEXT NOT NULL);
Query OK, 0 rows affected (0,00 sec)
mysql> INSERT INTO t1 VALUES (1, 'Luis');
Query OK, 1 row affected (0,01 sec)
17.2.1.5 增加一个实例到Group
这个时候已经有一个成员了s1,已经有了一些数据,现在加入其它节点到Group
增加s2 到group,设置配置文件,基本和s1的一直,修改server_id,因为文档中是本地多实例,需要修改datadir等信息。
设置用于复制的用户:
SET SQL_LOG_BIN=0;
CREATE USER rpl_user@'%';
GRANT REPLICATION SLAVE ON *.* TO rpl_user@'%' IDENTIFIED BY 'rpl_pass';
SET SQL_LOG_BIN=1;
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';
Query OK, 0 rows affected (0,01 sec)
这里和s1不一样的地方是不需要。
通过 performance_schema.replication_group_members 检查成员是不是正常。
查看之前s1插入的数据时候已经完全同步过来。
17.3 监控Group Replication
使用performance schema 上的表来监控Group Replication,如果有performance_ schema那么就会在上面创建来个表:
· performance_schema.replication_group_member_stats
· performance_schema.replication_group_members
· performance_schema.replication_connection_status
· performance_schema.replication_applier_status
· group_replication_recovery
· group_replication_applier
17.3.1 Replication_group_member_stats
Field |
Description |
Channel_name |
Group Replication通道名 |
Member_id |
成员的uuid |
Count_transactions_in_queue |
未经过冲突检查的事务数量 |
Count_transactions_checked |
通过冲突检查的事务数量 |
Count_conflicts_detected |
没有通过冲突检查的事务数量 |
Count_transactions_rows_validating |
冲突检查数据库的大小 |
Transactions_committed_all_members |
成功提交到成员的事务数量 |
Last_conflict_free_transaction |
最后一次冲突,被释放的事务 |
17.3.2 Replication_group_members
Field |
Description |
Channel_name |
通道名 |
Member_id |
成员uuid |
Member_host |
成员host |
Member_port |
成员端口 |
Member_state |
成员状态 (which can be ONLINE, ERROR, RECOVERING, OFFLINE or UNREACHABLE). |
17.3.3 Replication_connection_status
Field |
Description |
Channel_name |
通道名 |
Group_name |
Group名 |
Source_UUID |
Group的标识 |
Service_state |
查看服务是否是group成员{ON, OFF and CONNECTING}; |
Received_transaction_set |
已经被该成员接受的gtid集 |
17.3.4 Replication_applier_status
Field |
Description |
Channel_name |
通道名 |
Service_state |
服务状态 |
Remaining_delay |
是否配置了延迟 |
Count_transactions_retries |
重试执行的事务个数 |
Received_transaction_set |
已经被接收的gtid集 |
17.3.5 Group Replication Server States
表replication_group_members在view发生变化的时候就会修改,比如group的配置动态变化。如果出现网络分离,或者服务离开group,信息就会被报告,根据不通的服务获得的信息不通。注意如果服务离开了group,那么就无法获得其他服务的信息。如果发生分离,比如quorum丢失,服务就不能相互进行协同。也就是说会报告unreachable而不会一个假设状态。
Field |
Description |
Group Synchronized |
ONLINE |
服务online可以提供全部服务 |
Yes |
RECOVERING |
成员正在恢复,之后会变成online黄台 |
No |
OFFLINE |
插件已经安装,但是成员不属于任何group |
No |
ERROR |
在recovery阶段或者应用修改的时候,出现错误 |
No |
UNREACHABLE |
错误排查怀疑服务无法连接。 |
No |
17.4 Group Replication操作
17.4.1部署多主或者单主模式
Group Replication有2个不同的模式:
1. 单主模式
2. 多主模式
默认是单主模式的,不能的模式不能出现在一个group中,比如一个成员是单主,一个成员是多主。切换模式需要重新配置,然后重启。不管什么模式,Group Replication都不支持failover。这个必须由程序自己来处理,或者用其他中间件。
当不是了多主,语句是可以兼容的,当在多主模式,以下情况是会被检查语句的:
1. 如果一个事务执行在serializable隔离级别,但是提交失败
2. 如果事务执行的表有外键,但是提交失败
当然检查可以通过group_replication_enforce_update_everywhere_checks来关闭。
17.4.1.1 单主模式
在单主模式下,只有主是可以读写的,其他都只能读取。这个设置是自动的。主通常是关联到group的,其他的成员join,自动学习主,并且设置为只读。
在单主模式下,多主的检查被取消,因为系统只有一个服务是可写的。当主成员失败,自动主选举机制会选取新的主。然后新竹根据成员的uuid进行排序然后选择第一个。
当主离开Group,也会选举新主,一旦新主被选出来之后,就会设置可读写,其他任然是从。
17.4.1.2 多主模式
在多主模式下,和单主不通,不需要选举产生多主,服务没有特定的角色。所有的服务都是可读写的。
17.4.1.3 查找Primary
Primary 可以通过show status 或者select查找:
mysql> SELECT VARIABLE_VALUE FROM performance_schema.global_status WHERE VARIABLE_NAME= 'group_replication_primary_member';
+--------------------------------------+
| VARIABLE_VALUE |
+--------------------------------------+
| 69e1a3b8-8397-11e6-8e67-bf68cbc061a4 |
+--------------------------------------+
1 row in set (0,00 sec)
17.4.2 协调Recovery
当一个新的成员要加入到group,会连接到一个合适的donor并且获取数据,成员会一直获取直到状态变为online。
Donor选择
Donor选择是随机的在group中选一个成员。同一个成员不会被选择多次。如果连接到donor失败,那么会自动或去连接新的donor,一旦超过连接重试限制就会报错。
强制自动Donor切换
出现以下问题的时候会自动切换到一个新的donor,并尝试连接:
1. 清理数据场景,如果被选择的donor包含数据清理,但是是recovery需要的,那么会产生错误并且,获取一个新的donor。
2. 重复数据,如果一个joiner已经包含了一些数据,和selected的有冲突,那么也会报告错误,并且选择一个新的donor。
3. 其他错误,任何recovery线程的错误都会触发,连接一个新的donor。
Donor连接重试
Recovery数据的传输是依赖binlog和现存的MySQL复制框架,因此可能会有一些传输问题导致receiver或者applier有问题。这个时候会有donor切换。
重试次数
默认从donor pool里面可以尝试10次连接,也可以通过参数修改,一下脚本设置成了10次:
SET GLOBAL group_replication_recovery_retry_count= 10;
Sleep Routines
通过参数设置:
SET GLOBAL group_replication_recovery_reconnect_interval= 120;
设置为120秒,只有当joiner尝试连接了所有的donor,但是没有合适的,并且没有剩余的,那么按照参数来sleep。
17.4.3 网络隔离
17.4.3.1 发现网络隔离
Replication_group_members包含了当前view里面的所有服务的和服务的状态。大多数情况下服务运行是正常的,所以这个表对所有服务来说是一致的。如果出现网络隔离,那么quorum就会丢失,然后表上回显示UNREACHABLE。
比如有个场景有5个服务,然后因为事故,其中3个丢失:
· Server s1 with member identifier 199b2df7-4aaf-11e6-bb16-28b2bd168d07
· Server s2 with member identifier 199bb88e-4aaf-11e6-babe-28b2bd168d07
· Server s3 with member identifier 1999b9fb-4aaf-11e6-bb54-28b2bd168d07
· Server s4 with member identifier 19ab72fc-4aaf-11e6-bb51-28b2bd168d07
· Server s5 with member identifier 19b33846-4aaf-11e6-ba81-28b2bd168d07
丢失之前的状态:
mysql> SELECT * FROM performance_schema.replication_group_members;
+---------------------------+--------------------------------------+-------------+-------------+--------------+
| CHANNEL_NAME | MEMBER_ID | MEMBER_HOST | MEMBER_PORT | MEMBER_STATE |
+---------------------------+--------------------------------------+-------------+-------------+--------------+
| group_replication_applier | 1999b9fb-4aaf-11e6-bb54-28b2bd168d07 | 127.0.0.1 | 13002 | ONLINE |
| group_replication_applier | 199b2df7-4aaf-11e6-bb16-28b2bd168d07 | 127.0.0.1 | 13001 | ONLINE |
| group_replication_applier | 199bb88e-4aaf-11e6-babe-28b2bd168d07 | 127.0.0.1 | 13000 | ONLINE |
| group_replication_applier | 19ab72fc-4aaf-11e6-bb51-28b2bd168d07 | 127.0.0.1 | 13003 | ONLINE |
| group_replication_applier | 19b33846-4aaf-11e6-ba81-28b2bd168d07 | 127.0.0.1 | 13004 | ONLINE |
+---------------------------+--------------------------------------+-------------+-------------+--------------+
5 rows in set (0,00 sec)
然后因为事故quorum丢失:
mysql> SELECT * FROM performance_schema.replication_group_members;
+---------------------------+--------------------------------------+-------------+-------------+--------------+
| CHANNEL_NAME | MEMBER_ID | MEMBER_HOST | MEMBER_PORT | MEMBER_STATE |
+---------------------------+--------------------------------------+-------------+-------------+--------------+
| group_replication_applier | 1999b9fb-4aaf-11e6-bb54-28b2bd168d07 | 127.0.0.1 | 13002 | UNREACHABLE |
| group_replication_applier | 199b2df7-4aaf-11e6-bb16-28b2bd168d07 | 127.0.0.1 | 13001 | ONLINE |
| group_replication_applier | 199bb88e-4aaf-11e6-babe-28b2bd168d07 | 127.0.0.1 | 13000 | ONLINE |
| group_replication_applier | 19ab72fc-4aaf-11e6-bb51-28b2bd168d07 | 127.0.0.1 | 13003 | UNREACHABLE |
| group_replication_applier | 19b33846-4aaf-11e6-ba81-28b2bd168d07 | 127.0.0.1 | 13004 | UNREACHABLE |
+---------------------------+--------------------------------------+-------------+-------------+--------------+
5 rows in set (0,00 sec)
因为大多数已经丢失,所以Group就无法继续运行。为了让Group恢复运行需要重置group成员列表。或者关闭s1,s2的group replication,然后解决s3,s4,s5出现的问题,然后重启group replication。
17.4.3.2 Unblocking a Partition
Group Replication可以强制成员配置来重置。一下场景只有S1,S2,就可以强制成员列表,通过设置变量group_replication_force_members变量。
假设S1,S2存活,其他都非预期退出group,想要强制成员只有S1,S2。
首先查看S1上的成员列表:
mysql> SELECT * FROM performance_schema.replication_group_members;
+---------------------------+--------------------------------------+-------------+-------------+--------------+
| CHANNEL_NAME | MEMBER_ID | MEMBER_HOST | MEMBER_PORT | MEMBER_STATE |
+---------------------------+--------------------------------------+-------------+-------------+--------------+
| group_replication_applier | 1999b9fb-4aaf-11e6-bb54-28b2bd168d07 | 127.0.0.1 | 13002 | UNREACHABLE |
| group_replication_applier | 199b2df7-4aaf-11e6-bb16-28b2bd168d07 | 127.0.0.1 | 13001 | ONLINE |
| group_replication_applier | 199bb88e-4aaf-11e6-babe-28b2bd168d07 | 127.0.0.1 | 13000 | ONLINE |
| group_replication_applier | 19ab72fc-4aaf-11e6-bb51-28b2bd168d07 | 127.0.0.1 | 13003 | UNREACHABLE |
| group_replication_applier | 19b33846-4aaf-11e6-ba81-28b2bd168d07 | 127.0.0.1 | 13004 | UNREACHABLE |
+---------------------------+--------------------------------------+-------------+-------------+--------------+
5 rows in set (0,00 sec)
然后从S1,S2中获取@@group_replication_local_address,然后设置到变量中
mysql> SELECT @@group_replication_local_address;
+-----------------------------------+
| @@group_replication_local_address |
+-----------------------------------+
| 127.0.0.1:10000 |
+-----------------------------------+
1 row in set (0,00 sec)
mysql> SELECT @@group_replication_local_address;
+-----------------------------------+
| @@group_replication_local_address |
+-----------------------------------+
| 127.0.0.1:10001 |
+-----------------------------------+
1 row in set (0,00 sec)
mysql> SET GLOBAL group_replication_force_members="127.0.0.1:10000,127.0.0.1:10001";
Query OK, 0 rows affected (7,13 sec)
检查members
mysql> select * from performance_schema.replication_group_members;
+---------------------------+--------------------------------------+-------------+-------------+--------------+
| CHANNEL_NAME | MEMBER_ID | MEMBER_HOST | MEMBER_PORT | MEMBER_STATE |
+---------------------------+--------------------------------------+-------------+-------------+--------------+
| group_replication_applier | b5ffe505-4ab6-11e6-b04b-28b2bd168d07 | 127.0.0.1 | 13000 | ONLINE |
| group_replication_applier | b60907e7-4ab6-11e6-afb7-28b2bd168d07 | 127.0.0.1 | 13001 | ONLINE |
+---------------------------+--------------------------------------+-------------+-------------+--------------+
2 rows in set (0,00 sec)
当强制一个新的成员配置,要保证其他服务是停止了。在场景中S3,S4,S5如果不是真的unreachable其实是online
推荐阅读
-
MySQL-group-replication 配置步骤(推荐)
-
MySQL-group-replication 配置步骤(推荐)
-
MySQL8.0.16新特性:The Communication Protocol In Group Replication
-
[MySQL Reference Manual]17 Group Replication
-
MySQL Group Replication 多机多实例安装配置(Windows环境)
-
Mysql Group Replication 主从(单主)中间件ProxySQL安装配置
-
MySQL Group Replication 多机多实例安装配置
-
MySQL Group Replication 单机多实例安装配置
-
MySQL Group Replication配置
-
mysql group replication观点及实践