一、前言
mysql應該是廣大開發們用的最多的數據庫了。單節點mysql沒啥好說的,官方文檔看起來就行了。不過對於集羣來說,高可用這些就有點迷糊了,今天這個文章只是淺層次的總結一下。在5.7.17的官方文檔中有詳細地描述如何設置Single-Primary MGR的方法。Deploying Group Replication in Single-Primary Mode(https://dev.mysql.com/doc/refman/5.7/en/group-replication-deploying-in-single-primary-mode.html)
MGR(MySQL Group Replication)是MySQL官方在5.7.17版本引進的一個數據庫高可用與高擴展的解決方案,以插件形式提供,實現了分佈式下數據的最終已執行,總結MGR的特點如下:
- 高一致性:基於分佈式paxos協議實現組複製,保證數據一致性
- 高容錯性:自動檢測機制,只要不是大多數節點都宕機就可以繼續工作,內置防腦裂保護機制;
- 高擴展性:節點的添加與移除會自動更新組成員信息,新節點加入後,自動從其他節點同步增量數據,知道與其他節點數據一致;
- 高靈活性:提供單住和多主模式,單主模式在主庫宕機後能夠自動選主,所有寫入都在主節點進行,多主模式支持多節點寫入。
二、知識點
主從複製,一主多從,主庫提供讀寫功能,從庫提供只讀功能。當一個事務在master 提交成功時,會把binlog文件同步到從庫服務器上落地爲relay log給slave端執行,這個過程主庫是不考慮從庫是否有接收到binlog文件,有可能出現這種情況,當主庫commit一個事務後,數據庫發生宕機,剛好它的binlog還沒來得及傳送到slave端,這個時候選任何一個slave端都會丟失這個事務,造成數據不一致情況。 爲了避免出現主從數據不一致的情況,MySQL引入了半同步複製,添加多了一個從庫反饋機制,即半同步複製。這個有兩種方式設置:
- 主庫執行完事務後,同步binlog給從庫,從庫ack反饋接收到binlog,主庫提交commit,反饋給客戶端,釋放會話;
- 主庫執行完事務後,主庫提交commit ,同步binlog給從庫,從庫ack反饋接收到binlog,反饋給客戶端,釋放會話;
但是,雖然滿足了一主多從,讀寫分析,數據一致,但是,依舊有兩個弊端:
- 寫操作只能在master上;
- 如果master宕機,需要人爲選擇新主並重新給其他的slave端執行change master;
爲了解決一系列問題,官方推出了MySQL Group Replication,從group replication發佈以後,就有3種方法來實現MySQL的高可用集羣:
- 異步複製
- 半同步複製
- group replication
三、Group Replication原理
MySQL Group Replication有兩種模式,單主模式single-primary mode和多主模式multi-primary mode,在同一個group內,不允許兩種模式同時存在,並且若要切換到不同模式,必須修改配置後重新啓動集羣。
1、單主模式
在單主模式下,只有一個節點可以讀寫,其他節點提供只讀服務。單主模式下,該參數 _ 必須被設置爲 FALSE ,當主節點宕掉,自動會根據服務器的server_uuid變量和group_replication_member_weight變量值,選擇下一個slave誰作爲主節點,group_replication_member_weight的值最高的成員被選爲新的主節點,該參數默認爲50,建議可以在節點上設置不同值;在group_replication_member_weight值相同的情況下,group根據數據字典中 server_uuid排序,排序在最前的被選擇爲主節點。
- 單主模式中發現當前的主服務器,該值VARIABLE_VALUE爲實例節點的server_uuid:
select * from performance_schema.global_status WHERE VARIABLE_NAME like '%group_replication%';
四、簡單查詢
# 開啓單主模式
mysql> set global group_replication_single_primary_mode=on;
Query OK, 0 rows affected (0.00 sec)
mysql> SET GLOBAL group_replication_bootstrap_group=ON;
Query OK, 0 rows affected (0.00 sec)
# 設置使用組複製的用戶
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.07 sec)
mysql> start group_replication;
Query OK, 0 rows affected, 1 warning (2.08 sec)
mysql> SET GLOBAL group_replication_bootstrap_group=OFF;
Query OK, 0 rows affected (0.00 sec)
mysql> select * from performance_schema.replication_group_members;
+---------------------------+--------------------------------------+-------------+-------------+--------------+
| CHANNEL_NAME | MEMBER_ID | MEMBER_HOST | MEMBER_PORT | MEMBER_STATE |
+---------------------------+--------------------------------------+-------------+-------------+--------------+
| group_replication_applier | 1fa7b3ca-9475-11e8-a217-5254004e7cfe | 172.17.0.48 | 3306 | ONLINE |
| group_replication_applier | 81d824f1-90ba-11e8-a83d-52540043d75a | 172.17.0.2 | 3306 | ONLINE |
| group_replication_applier | b13df29e-90b6-11e8-8d1b-525400fc3993 | 172.17.0.37 | 3306 | ONLINE |
+---------------------------+--------------------------------------+-------------+-------------+--------------+
3 rows in set (0.00 sec)
mysql> show variables like '%read_on%';
+-----------------------+-------+
| Variable_name | Value |
+-----------------------+-------+
| innodb_read_only | OFF |
| read_only | OFF |
| super_read_only | OFF |
| transaction_read_only | OFF |
| tx_read_only | OFF |
+-----------------------+-------+
5 rows in set (0.00 sec)
mysql> show variables like '%server_uuid%';
+---------------+--------------------------------------+
| Variable_name | Value |
+---------------+--------------------------------------+
| server_uuid | b13df29e-90b6-11e8-8d1b-525400fc3993 |
+---------------+--------------------------------------+
1 row in set (0.00 sec)
mysql> select * from performance_schema.global_status WHERE VARIABLE_NAME like '%group_replication%';
+----------------------------------+--------------------------------------+
| VARIABLE_NAME | VARIABLE_VALUE |
+----------------------------------+--------------------------------------+
| group_replication_primary_member | b13df29e-90b6-11e8-8d1b-525400fc3993 |
+----------------------------------+--------------------------------------+
1 row in set (0.01 sec)
mysql> show variables like '%group_replication_member_weight%';
+---------------------------------+-------+
| Variable_name | Value |
+---------------------------------+-------+
| group_replication_member_weight | 80 |
+---------------------------------+-------+
1 row in set (0.00 sec)
1、登錄到數據庫
mysql > mysql -uroot -pyourpassword
2、關閉二進制日誌記錄功能
mysql > set sql_log_bin=0;
3、創建一個用於複製的用戶,不建議用root用戶
mysql > grant replication slave on *.* to rpl_user@'%' identified by 'rpl_pass';
mysql > flush privileges;
4、開啓二進制日誌記錄功能
mysql > set sql_sql_log_bin = 1;
5、 設置使用組複製的用戶
mysql > change master to master_user='rpl_user',master_password='rpl_pass' for channel 'group_replication_recovery';
6、安裝組複製插件
mysql > install PLUGIN group_replication SONAME 'group_replication.so';
7、開啓插件自動引用組功能
mysql > set global group_replication_bootstrap_group = ON;
8、 開啓組複製
mysql > start group_replication;
9、關閉插件自動引用組功能
mysql > set global group_replication_bootstrap_group = OFF;
10、查看組內節點和節點狀態
查看組內成員
mysql> select * from performance_schema.replication_group_members;
+---------------------------+--------------------------------------+----------------------------------------+-------------+--------------+
| CHANNEL_NAME | MEMBER_ID | MEMBER_HOST | MEMBER_PORT | MEMBER_STATE |
+---------------------------+--------------------------------------+----------------------------------------+-------------+--------------+
| group_replication_applier | 5d5b3ceb-9cdc-11ea-a3f6-0242ac11000e | mysql-cluster-0.mysql-cluster-gvr.test | 3306 | ONLINE |
| group_replication_applier | 70f1b749-9cdc-11ea-b2a7-0242ac11000f | mysql-cluster-1.mysql-cluster-gvr.test | 3306 | ONLINE |
+---------------------------+--------------------------------------+----------------------------------------+-------------+--------------+
2 rows in set (0.01 sec)
-
CHANNEL_NAME : 顯示的值永遠爲group_replication_applier
-
MEMBER_ID : 節點serer_uuid
-
MEMBER_PORT : 節點服務端口,取值爲server_port指定的端口
-
MEMBER_HOST : 如果沒有配置report_host選項,那麼取值爲機器的hostname,可以通過report_host配置指定具體的IP
-
MEMBER_STATE : 節點狀態
-
MEMBER_STATE字段顯示當前節點的狀態,根據官方文檔,取值和介紹如下所示:
取值 | 解釋 | 狀態是否在集羣內同步 |
---|---|---|
ONLINE | 表示該節點可正常提供服務 | YES |
RECOVERING | 表示當前節點正在從其他節點恢復數據 | YES |
OFFLINE | 表示GR插件已經加載,但是該節點不屬於任何一個GR組 | NO |
ERROR | 表示節點在recovery階段出現錯誤或者從其他節點同步狀態中出現錯誤 | NO |
UNREACHABLE | 節點處於不可達狀態,無法與之發生網絡通訊 | NO |
從上表可以知道,只有ONLINE和RECOVERING兩種狀態會在集羣中得到同步。這個狀態同步是指狀態在所有節點上面查詢均能保持一致的意思。至於OFFLINE,ERROR和UNREABLE,做以下說明:
- 只有在當前OFFLINE節點查詢replication_group_members表才能得到OFFLINE狀態,在其他節點上查詢replication_group_members表,則一般沒有該節點的狀態(很好理解,因爲OFFLINE節點已經不屬於這個GR組了)
- 只有在當前ERROR節點查詢replication_group_members表才能得到ERROR狀態,同上面的OFFLINE,在其他節點上查詢也看不到該節點
- 假設節點A與B網絡通訊失敗,那麼在節點A上查詢replication_group_members表,有可能得到B的狀態爲UNREACHABLE
五、題外話(MGR的限制)
-
僅支持InnoDB表,並且每張表一定要有一個主鍵,用於做write set的衝突檢測;
-
必須打開GTID特性,二進制日誌格式必須設置爲ROW,用於選主與write set
-
COMMIT可能會導致失敗,類似於快照事務隔離級別的失敗場景
-
目前一個MGR集羣最多支持9個節點
-
不支持外鍵於save point特性,無法做全局間的約束檢測與部分部分回滾
-
二進制日誌不支持binlog event checksum
六、參考資料
參考文章1:https://yq.aliyun.com/articles/702208
參考文章2:https://www.jianshu.com/p/cbe3ba27295c
參考文章3:https://database.51cto.com/art/202004/615706.htm?mobile