MySQL 組復制實現了基於復制協議的多主更新(單主模式)。
復制組由多個 server成員構成,並且組中的每個 server 成員可以獨立地執行事務。但所有讀寫(RW)事務只有在沖突檢測成功后才會提交。只讀(RO)事務不需要在沖突檢測,可以立即提交。
對於任何 RW 事務,提交操作並不是由始發 server 單向決定的,而是由組來決定是否提交。准確地說,在始發 server 上,當事務准備好提交時,該 server 會廣播寫入值(已改變的行)和對應的寫入集(已更新的行的唯一標識符)。然后會為該事務建立一個全局的順序。最終,這意味着所有 server 成員以相同的順序接收同一組事務。因此,所有 server 成員以相同的順序應用相同的更改,以確保組內一致。
組復制使您能夠根據在一組 server 中復制系統的狀態來創建具有冗余的容錯系統。因此,只要它不是全部或多數 server 發生故障,即使有一些 server 故障,系統仍然可用,最多只是性能和可伸縮性降低,但它仍然可用。server 故障是孤立並且獨立的。它們由組成員服務來監控,組成員服務依賴於分布式故障檢測系統,其能夠在任何 server 自願地或由於意外停止而離開組時發出信號。
他們是由一個分布式恢復程序來確保當有 server 加入組時,它們會自動更新組信息到最新。並且多主更新確保了即使在單個服務器故障的情況下也不會阻止更新,不必進行 server故障轉移。因此,MySQL 組復制保證數據庫服務持續可用。
值得注意的一點是,盡管數據庫服務可用,但當有一個 server 崩潰時,連接到它的客戶端必須定向或故障轉移到不同的 server。 這不是組復制要解決的問題;可以用mysql-router 或者其他中間件,比如mycat、altas等。
架構圖如下

限制
表需要有主鍵
采用GTID+binlog的方式進行復制
復制事件校驗 binlog_checksum=none
Gap Locks不可用
多主模式下限制
隔離級別
官網建議使用READ COMMITTED級別,除非應用程序依賴於REPLEATABLE READ,RC模式下沒有GAP LOCK,比較好支持Innodb本身的沖突檢測機制何組復制的內部分布式檢測機制一起協同工作。不支持SERIALIZABLE隔離級別
外鍵
不建議使用級聯外鍵,如果使用必須配置group_replication_enforce_update_everywhere_checks=ON
DDL操作
多主不支持同一對象不同實例的並發的DDL+DML混合操作 ,MySQL5.7上的DDL不是原子操作無法回滾,因此group replication沒有對DDL做沖突檢測,可能導致數據不一致;應用或中間件要能夠把所有的DDL語句轉到同一台MySQL上去執行。
本次測試環境
192.168.20.201 redis01
192.168.20.202 redis02
192.168.20.203 redis03
編輯my.cnf
#REP server-id=1 log-bin=mysql-bin gtid_mode = ON enforce_gtid_consistency = ON master_info_repository =TABLE relay_log_info_repository=TABLE binlog_checksum=NONE log_slave_updates=ON binlog_format=ROW #Group Replication Settings transaction_write_set_extraction=XXHASH64 loose-group_replication_group_name="f27d825f-792f-11e8-b745-0800272bcfc4" loose-group_replication_start_on_boot=off loose-group_replication_local_address= "192.168.20.201:24901" loose-group_replication_group_seeds= "192.168.20.201:24901,192.168.20.202:24902,192.168.20.203:24903" loose-group_replication_bootstrap_group=off 每個mysql的service-id不一樣 地址也需要更改下,其他全部都一樣
重啟redis01主機上的mysql讓配置生效
[root@redis01 ~]# service mysqld restart
Stopping mysqld: [ OK ]
Starting mysqld: [ OK ]
備份redis01
innobackupex -uxbackup -u root -p ocm123 --no-timestamp /data/backup/
在redis02、redis03上恢復數據
innobackupex --copy-back /data/backup
redis01當作主機點 first node
set global validate_password_policy=LOW;
set global validate_password_length=4;
create user 'repl'@'192.%' identified by 'ocm123';
GRANT replication slave ON *.* to repl@'192.%' IDENTIFIED BY 'ocm123';
flush privileges;
CHANGE MASTER TO MASTER_USER='repl', MASTER_PASSWORD='ocm123' FOR CHANNEL 'group_replication_recovery';
INSTALL PLUGIN group_replication SONAME 'group_replication.so';
reset master;
SET GLOBAL group_replication_bootstrap_group=ON;
START GROUP_REPLICATION;
SET GLOBAL group_replication_bootstrap_group=off;
查看日志,redis01作為主成員
1 2018-07-07T10:25:14.889679Z 7 [Note] Plugin group_replication reported: 'Group communication SSL configuration: group_replication_ssl_mode: "DISABLED"' 2 2018-07-07T10:25:14.889959Z 7 [Note] Plugin group_replication reported: '[GCS] Added automatically IP ranges 10.0.2.15/24,127.0.0.1/8,192.168.122.1/24,192.168.20.201/24 to the whitelist' 3 2018-07-07T10:25:14.890320Z 7 [Warning] Plugin group_replication reported: '[GCS] Automatically adding IPv4 localhost address to the whitelist. It is mandatory that it is added.' 4 2018-07-07T10:25:14.890421Z 7 [Note] Plugin group_replication reported: '[GCS] SSL was not enabled' 5 2018-07-07T10:25:14.890465Z 7 [Note] Plugin group_replication reported: 'Initialized group communication with configuration: group_replication_group_name: "f27d825f-792f-11e8-b745-0800272bcfc4"; group_replication_local_address: "192.168.20.201:24901"; group_replication_group_seeds: "192.168.20.201:24901,192.168.20.202:24902,192.168.20.203:24903"; group_replication_bootstrap_group: true; group_replication_poll_spin_loops: 0; group_replication_compression_threshold: 1000000; group_replication_ip_whitelist: "AUTOMATIC"' 6 2018-07-07T10:25:14.890603Z 7 [Note] Plugin group_replication reported: '[GCS] Configured number of attempts to join: 0' 7 2018-07-07T10:25:14.890785Z 7 [Note] Plugin group_replication reported: '[GCS] Configured time between attempts to join: 5 seconds' 8 2018-07-07T10:25:14.890816Z 7 [Note] Plugin group_replication reported: 'Member configuration: member_id: 1; member_uuid: "3281175c-7a55-11e8-9cc7-080027c8ffe9"; single-primary mode: "true"; group_replication_auto_increment_increment: 7; ' 9 2018-07-07T10:25:14.922055Z 10 [Note] 'CHANGE MASTER TO FOR CHANNEL 'group_replication_applier' executed'. Previous state master_host='', master_port= 3306, master_log_file='', master_log_pos= 4, master_bind=''. New state master_host='<NULL>', master_port= 0, master_log_file='', master_log_pos= 4, master_bind=''. 10 2018-07-07T10:25:14.954193Z 13 [Note] Slave SQL thread for channel 'group_replication_applier' initialized, starting replication in log 'FIRST' at position 0, relay log './redis01-relay-bin-group_replication_applier.000001' position: 4 11 2018-07-07T10:25:14.954214Z 7 [Note] Plugin group_replication reported: 'Group Replication applier module successfully initialized!' 12 2018-07-07T10:25:14.954233Z 7 [Note] Plugin group_replication reported: 'auto_increment_increment is set to 7' 13 2018-07-07T10:25:14.954240Z 7 [Note] Plugin group_replication reported: 'auto_increment_offset is set to 1' 14 2018-07-07T10:25:14.974409Z 0 [Note] Plugin group_replication reported: 'XCom protocol version: 3' 15 2018-07-07T10:25:14.974512Z 0 [Note] Plugin group_replication reported: 'XCom initialized and ready to accept incoming connections on port 24901' 16 2018-07-07T10:25:15.977185Z 16 [Note] Plugin group_replication reported: 'Only one server alive. Declaring this server as online within the replication group' 17 2018-07-07T10:25:15.978257Z 0 [Note] Plugin group_replication reported: 'Group membership changed to redis01:3306 on view 15309591159762880:1.' 18 2018-07-07T10:25:15.983526Z 0 [Note] Plugin group_replication reported: 'This server was declared online within the replication group' 19 2018-07-07T10:25:15.983793Z 0 [Note] Plugin group_replication reported: 'A new primary with address redis01:3306 was elected, enabling conflict detection until the new primary applies all relay logs.' 20 2018-07-07T10:25:15.983927Z 18 [Note] Plugin group_replication reported: 'This server is working as primary member.'
在redis02上加組之前創建表
CREATE TABLE ht.tb(id int primary key, name varchar(16));
INSERT INTO ht.tb VALUES(1,'zhou'),(2,'430'),(3,'YYF'),(4,'ChuaN'),(5,'Faith');
在redis02、redis03上
set global validate_password_policy=LOW;
set global validate_password_length=4;
create user 'repl'@'192.%' identified by 'ocm123';
GRANT replication slave ON *.* to repl@'192.%' IDENTIFIED BY 'ocm123';
flush privileges;
CHANGE MASTER TO MASTER_USER='repl', MASTER_PASSWORD='ocm123' FOR CHANNEL 'group_replication_recovery';
INSTALL PLUGIN group_replication SONAME 'group_replication.so';
set global group_replication_allow_local_disjoint_gtids_join=ON;
reset slave;
START GROUP_REPLICATION;
用xtrabackup做備份恢復,即使first節點沒有新數據插入也會報This member has more executed transactions than those present in the group 錯誤加不進去組;測試加組前在redis01上創建表及插入數據也同步過去;
在redis03上加組之前在redis01上繼續插入數據
INSERT INTO ht.tb VALUES(6,'zhou'),(7,'430'),(8,'YYF'),(9,'ChuaN'),(10,'Faith');
加組前在redis01上創建表及插入數據也同步過去
mysql> select * from ht.tb;
+----+-------+
| id | name |
+----+-------+
| 1 | zhou |
| 2 | 430 |
| 3 | YYF |
| 4 | ChuaN |
| 5 | Faith |
| 6 | zhou |
| 7 | 430 |
| 8 | YYF |
| 9 | ChuaN |
| 10 | Faith |
+----+-------+
10 rows in set (0.00 sec)
查看組成員
mysql> SELECT * FROM performance_schema.replication_group_members;
+---------------------------+--------------------------------------+-------------+-------------+--------------+
| CHANNEL_NAME | MEMBER_ID | MEMBER_HOST | MEMBER_PORT | MEMBER_STATE |
+---------------------------+--------------------------------------+-------------+-------------+--------------+
| group_replication_applier | 11c530de-81e0-11e8-9fbe-0800276bf78a | redis03 | 3306 | ONLINE |
| group_replication_applier | 13339747-81e0-11e8-8ef2-080027e68d01 | redis02 | 3306 | ONLINE |
| group_replication_applier | 1384a263-81e0-11e8-b88c-080027c8ffe9 | redis01 | 3306 | ONLINE |
+---------------------------+--------------------------------------+-------------+-------------+--------------+
3 rows in set (0.00 sec)
查看那個可以是primary
mysql> SHOW STATUS LIKE 'group_replication_primary_member';
+----------------------------------+--------------------------------------+
| Variable_name | Value |
+----------------------------------+--------------------------------------+
| group_replication_primary_member | 1384a263-81e0-11e8-b88c-080027c8ffe9 |
+----------------------------------+--------------------------------------+
1 row in set (0.00 sec)
mysql> SELECT a.member_host FROM performance_schema.replication_group_members a INNER JOIN performance_schema.global_status b where a.member_id=b.variable_value;
+-------------+
| member_host |
+-------------+
| redis01 |
+-------------+
1 row in set (0.00 sec)
查看恢復狀態
mysql> show slave status for channel 'group_replication_recovery' \G
*************************** 1. row ***************************
Slave_IO_State:
Master_Host: <NULL>
Master_User: repl
Master_Port: 0
Connect_Retry: 60
Master_Log_File:
Read_Master_Log_Pos: 4
Relay_Log_File: redis02-relay-bin-group_replication_recovery.000001
Relay_Log_Pos: 4
Relay_Master_Log_File:
Slave_IO_Running: No
Slave_SQL_Running: No
Replicate_Do_DB:
Replicate_Ignore_DB:
Replicate_Do_Table:
Replicate_Ignore_Table:
Replicate_Wild_Do_Table:
Replicate_Wild_Ignore_Table:
Last_Errno: 0
Last_Error:
Skip_Counter: 0
Exec_Master_Log_Pos: 0
Relay_Log_Space: 497
Until_Condition: None
Until_Log_File:
Until_Log_Pos: 0
Master_SSL_Allowed: No
Master_SSL_CA_File:
Master_SSL_CA_Path:
Master_SSL_Cert:
Master_SSL_Cipher:
Master_SSL_Key:
Seconds_Behind_Master: NULL
Master_SSL_Verify_Server_Cert: No
Last_IO_Errno: 0
Last_IO_Error:
Last_SQL_Errno: 0
Last_SQL_Error:
Replicate_Ignore_Server_Ids:
Master_Server_Id: 0
Master_UUID:
Master_Info_File: mysql.slave_master_info
SQL_Delay: 0
SQL_Remaining_Delay: NULL
Slave_SQL_Running_State:
Master_Retry_Count: 1
Master_Bind:
Last_IO_Error_Timestamp:
Last_SQL_Error_Timestamp:
Master_SSL_Crl:
Master_SSL_Crlpath:
Retrieved_Gtid_Set:
Executed_Gtid_Set: 13339747-81e0-11e8-8ef2-080027e68d01:1-3,
3281175c-7a55-11e8-9cc7-080027c8ffe9:1-90,
8b99bac3-81d2-11e8-b85d-080027c8ffe9:1-7
Auto_Position: 1
Replicate_Rewrite_DB:
Channel_Name: group_replication_recovery
Master_TLS_Version:
1 row in set (0.00 sec)
查看事件
mysql> SHOW BINLOG EVENTS;
+------------------+------+----------------+-----------+-------------+--------------------------------------------------------------------+
| Log_name | Pos | Event_type | Server_id | End_log_pos | Info |
+------------------+------+----------------+-----------+-------------+--------------------------------------------------------------------+
| mysql-bin.000001 | 4 | Format_desc | 1 | 123 | Server ver: 5.7.22-log, Binlog ver: 4 |
| mysql-bin.000001 | 123 | Previous_gtids | 1 | 150 | |
| mysql-bin.000001 | 150 | Gtid | 1 | 211 | SET @@SESSION.GTID_NEXT= '8b99bac3-81d2-11e8-b85d-080027c8ffe9:1' |
| mysql-bin.000001 | 211 | Query | 1 | 270 | BEGIN |
| mysql-bin.000001 | 270 | View_change | 1 | 369 | view_id=15309661790389352:1 |
| mysql-bin.000001 | 369 | Query | 1 | 434 | COMMIT |
| mysql-bin.000001 | 434 | Gtid | 1 | 495 | SET @@SESSION.GTID_NEXT= '8b99bac3-81d2-11e8-b85d-080027c8ffe9:2' |
| mysql-bin.000001 | 495 | Query | 1 | 554 | BEGIN |
| mysql-bin.000001 | 554 | View_change | 1 | 693 | view_id=15309661790389352:2 |
| mysql-bin.000001 | 693 | Query | 1 | 758 | COMMIT |
| mysql-bin.000001 | 758 | Gtid | 1 | 819 | SET @@SESSION.GTID_NEXT= '8b99bac3-81d2-11e8-b85d-080027c8ffe9:3' |
| mysql-bin.000001 | 819 | Query | 1 | 941 | use `ht`; CREATE TABLE ht.tb(id int primary key, name varchar(16)) |
| mysql-bin.000001 | 941 | Gtid | 1 | 1002 | SET @@SESSION.GTID_NEXT= '8b99bac3-81d2-11e8-b85d-080027c8ffe9:4' |
| mysql-bin.000001 | 1002 | Query | 1 | 1068 | BEGIN |
| mysql-bin.000001 | 1068 | Table_map | 1 | 1110 | table_id: 111 (ht.tb) |
| mysql-bin.000001 | 1110 | Write_rows | 1 | 1191 | table_id: 111 flags: STMT_END_F |
| mysql-bin.000001 | 1191 | Xid | 1 | 1218 | COMMIT /* xid=54 */ |
| mysql-bin.000001 | 1218 | Gtid | 1 | 1279 | SET @@SESSION.GTID_NEXT= '8b99bac3-81d2-11e8-b85d-080027c8ffe9:5' |
| mysql-bin.000001 | 1279 | Query | 1 | 1338 | BEGIN |
| mysql-bin.000001 | 1338 | View_change | 1 | 1477 | view_id=15309661790389352:4 |
| mysql-bin.000001 | 1477 | Query | 1 | 1542 | COMMIT |
| mysql-bin.000001 | 1542 | Gtid | 1 | 1603 | SET @@SESSION.GTID_NEXT= '8b99bac3-81d2-11e8-b85d-080027c8ffe9:6' |
| mysql-bin.000001 | 1603 | Query | 1 | 1669 | BEGIN |
| mysql-bin.000001 | 1669 | Table_map | 1 | 1711 | table_id: 111 (ht.tb) |
| mysql-bin.000001 | 1711 | Write_rows | 1 | 1792 | table_id: 111 flags: STMT_END_F |
| mysql-bin.000001 | 1792 | Xid | 1 | 1819 | COMMIT /* xid=88 */ |
| mysql-bin.000001 | 1819 | Gtid | 1 | 1880 | SET @@SESSION.GTID_NEXT= '8b99bac3-81d2-11e8-b85d-080027c8ffe9:7' |
| mysql-bin.000001 | 1880 | Query | 1 | 1939 | BEGIN |
| mysql-bin.000001 | 1939 | View_change | 1 | 2078 | view_id=15309661790389352:5 |
| mysql-bin.000001 | 2078 | Query | 1 | 2143 | COMMIT |
+------------------+------+----------------+-----------+-------------+--------------------------------------------------------------------+
到此1主2從搭建成功
多主模式
redis02 redis03 停止組復制
STOP GROUP_REPLICATION;
redis01上執行
STOP GROUP_REPLICATION;
SET GLOBAL group_replication_single_primary_mode=FALSE;
SET GLOBAL group_replication_enforce_update_everywhere_checks=TRUE;
SET GLOBAL group_replication_bootstrap_group=on;
START GROUP_REPLICATION;
SET GLOBAL group_replication_bootstrap_group=off;
在redis02 redis03 啟動組復制
SET GLOBAL group_replication_single_primary_mode=FALSE;
SET GLOBAL group_replication_enforce_update_everywhere_checks=TRUE;
START GROUP_REPLICATION;
SET GLOBAL group_replication_bootstrap_group=off;
檢查組成員及primary
mysql> SELECT * FROM performance_schema.replication_group_members;
+---------------------------+--------------------------------------+-------------+-------------+--------------+
| CHANNEL_NAME | MEMBER_ID | MEMBER_HOST | MEMBER_PORT | MEMBER_STATE |
+---------------------------+--------------------------------------+-------------+-------------+--------------+
| group_replication_applier | 11c530de-81e0-11e8-9fbe-0800276bf78a | redis03 | 3306 | ONLINE |
| group_replication_applier | 13339747-81e0-11e8-8ef2-080027e68d01 | redis02 | 3306 | ONLINE |
| group_replication_applier | 1384a263-81e0-11e8-b88c-080027c8ffe9 | redis01 | 3306 | ONLINE |
+---------------------------+--------------------------------------+-------------+-------------+--------------+
3 rows in set (0.00 sec)
mysql> SHOW STATUS LIKE 'group_replication_primary_member';
+----------------------------------+-------+
| Variable_name | Value |
+----------------------------------+-------+
| group_replication_primary_member | |
+----------------------------------+-------+
1 row in set (0.00 sec)
3個節點都可以讀寫,多主模式搭建完
mysql> show global variables like 'super%';
+-----------------+-------+
| Variable_name | Value |
+-----------------+-------+
| super_read_only | OFF |
+-----------------+-------+
1 row in set (0.00 sec)
在redis02上繼續插入數據
INSERT INTO ht.tb VALUES(11,'zhou'),(12,'430'),(13,'YYF'),(14,'ChuaN'),(15,'Faith');
在redis01上查詢
root@redis01> select * from ht.tb;
+----+-------+
| id | name |
+----+-------+
| 1 | zhou |
| 2 | 430 |
| 3 | YYF |
| 4 | ChuaN |
| 5 | Faith |
| 6 | zhou |
| 7 | 430 |
| 8 | YYF |
| 9 | ChuaN |
| 10 | Faith |
| 11 | zhou |
| 12 | 430 |
| 13 | YYF |
| 14 | ChuaN |
| 15 | Faith |
+----+-------+
15 rows in set (0.00 sec)
多主轉為單注
redis02 redis03 停止組復制
STOP GROUP_REPLICATION;
redis01上執行
STOP GROUP_REPLICATION;
SET GLOBAL group_replication_enforce_update_everywhere_checks=TRUE;
SET GLOBAL group_replication_bootstrap_group=on;
SET GLOBAL group_replication_single_primary_mode=TRUE;
START GROUP_REPLICATION;
SET GLOBAL group_replication_bootstrap_group=off;
在redis02 redis03 啟動組復制
set global group_replication_allow_local_disjoint_gtids_join=ON;
SET GLOBAL group_replication_single_primary_mode=off;
SET GLOBAL group_replication_enforce_update_everywhere_checks=TRUE;
START GROUP_REPLICATION;
SET GLOBAL super_read_only=on;
在安裝過程當中遇到的錯誤
1 2018-07-05T10:08:31.700840Z 0 [ERROR] Plugin group_replication reported: 'This member has more executed transactions than those present in the group. Local transactions: a7ca1853-7040-11e8-856a-08002771e31b:1-12, 2 f0019921-6d42-11e8-bd74-0800272bcfc4:1-3 > Group transactions: 0d01442d-8038-11e8-9d23-0800272bcfc4:1-3, 3 aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa:1-3, 4 f0019921-6d42-11e8-bd74-0800272bcfc4:1-16, 5 f27d825f-792f-11e8-b745-0800272bcfc4:1-7' 6 2018-07-05T10:08:31.700922Z 0 [ERROR] Plugin group_replication reported: 'The member contains transactions not present in the group. The member will now exit the group.' 7 2018-07-05T10:08:31.700928Z 0 [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;
Allow the current server to join the group even if it has transactions not present in the group.
錯誤日志
1 2018-07-05T10:48:19.726647Z 17 [ERROR] Slave SQL for channel 'group_replication_applier': Slave failed to initialize relay log info structure from the repository, Error_code: 1872 2 2018-07-05T10:48:19.726672Z 17 [ERROR] Plugin group_replication reported: 'Error while starting the group replication applier thread' 3 2018-07-05T10:48:19.726736Z 17 [Note] Plugin group_replication reported: 'The group replication applier thread was killed'
參考metalink解決
Cannot Configure Replication and RESET SLAVE ALL Does Not Work: "ERROR 1872 (HY000): Slave failed to initialize relay log info structure from the repository" (文檔 ID 2203190.1)
MySQL Innodb Cluster Node Failed To Start With Error: "[ERROR] Slave SQL for channel 'group_replication_applier': Slave failed to initialize relay log info structure from the repository, Error_code: 1872" (文檔 ID 2386403.1)
