天天看點

MGR初探

一、MGR基礎

1、複制背景

1.1 主從複制

傳統MySQL提供了一種簡單的主從複制方式,一個主,有一個或者多個從。主節點執行和送出事務,然後将他們發送到從節點,以重新執行(在基于語句的複制中)或者應用(在基于行的複制中)。這是一個 shared-nothing的系統,預設所有的server都有一個完整的資料副本。

MGR初探

MySQL異步複制

可以看到的是,異步複制是不考慮從庫有沒有接受binlog檔案的,是以會造成主從不一緻: 當主庫commit一個事務後,資料庫發生當機,剛好它的binlog還沒來得及傳送到slave端,這個時候選任何一個slave端都會丢失這個事務,造成資料不一緻情況。

是以還要一種半同步複制,它在協定中加了一個同步的步驟,這意味着主節點送出的時候需要等待從節點确認它已經收到了事物,隻有這樣主節點才能夠繼續送出。

MGR初探

MySQL半同步複制

從上面兩個圖中可以看到傳統的MySQL複制協定。藍色的箭頭表示不同的server之間或者server和client應用之間的資訊互動。

1.2 組複制

不管是異步複制還是半同步複制,都有兩個弊端:

  • 寫操作集中在MASTER伺服器上;
  • MASTER當機後,需要人為選擇新主并重新給其他的slave端執行change master(可用第三方工具實作,但是mysql的複制就是沒提供,是以也算是弊端)

    基于這種現狀,MySQL官方提供了 MySQL Group Replication。

MGR初探

MySQL組複制

相對于傳統的複制,MGR提供的功能有:

  • 多主:多寫模式下支援叢集中的所有節點都可以寫入
  • 一緻性: 依靠分布式一緻性協定(Paxos協定的變體)確定叢集中大部分節點收到日志
  • 彈性:同個MGR中,節點的加入或者移除都是自動調整
  • 可用性: 確定系統發生故障(包括腦裂)依然可用,雙寫對系統無影響

2、理論基礎

MGR有單主和多主兩種模式。

1.1 組複制

複制組由多個server成員組成,并且組中每個成員可以獨立的執行事務。但是所有的讀寫(RW)事務隻有在沖突檢測成功後才會送出。隻讀事務(RO)不需要沖突檢測,可以立即送出。

在始發server上,當事務準備好送出時,該server會廣播寫入值(已改變的行)和對應的寫入集(已更新行的唯一辨別符)。然後為該事物建立一個全局的順序。最終,這意味着所有server成員以相同的順序接收同一組事務。

是以,所有的server成員以相同的順序應用相同的更改,以確定組内一緻。

在不同的server上并發執行的事物可能存在沖突,根據組複制沖突檢測機制。如果在不同server上執行的兩個并發事務更新同一行,則存在沖突。沖突解決過程中,排在最前面的事物可以在所有server成員上送出,第二個事物在源server上復原,并且在組中其他server上删除。其實這就是分布式的先送出當選原則。

1.2 容錯

MySQL Group Replication建構于Paxos分布式算法的實作之上,以在伺服器之間提供分布式協調。是以,它需要大多數伺服器處于活動狀态才能達到仲裁成員數,進而做出決定。這直接影響系統可以容忍的故障數量,以及自身及其整體功能。容忍f個故障所需的伺服器數量 n= 2 x f + 1。

在實踐中,這意味着為了容忍一個故障,該組必須具有三個server。是以,如果一個server發生故障,仍然有兩個server構成多數(三分之二),并允許系統繼續自動做出決策并繼續進行。但是,如果第二個server以外fail掉 ,那麼該組(剩下一個server)會鎖定,因為沒有多數人可以達成協定。

MGR初探

二、部署安裝

1、單寫部署

官方文檔提供的是在一台伺服器上安裝3個mysql來搭建單主模式,這裡是按照官方文檔的步驟,但是部署在三台伺服器上。

1.1 環境:

MGR初探

1.2 配置檔案

編輯配置檔案/data1/my3306.cnf,3個節點 除了server_id、loose-group_replication_local_address、report_host 三個參數不一樣外,其他保持一緻。

#GTID
server_id=11
gtid_mode=ON
#強制gtid一緻性,開啟後對于特定create table不被支援
#ON:不允許任何事務違反GTID一緻性
enforce_gtid_consistency=ON

binlog_checksum=NONE
log_bin=binlog
log_slave_updates=ON
binlog_format=ROW
master_info_repository=TABLE
relay_log_info_repository=TABLE

#MGR
#定義用于生成辨別與事務關聯的寫入的哈希的算法,哈希值将用于分布式沖突檢測和處理
transaction_write_set_extraction=XXHASH64
#通知插件它正在加入或建立的組,可以使用SELECT UUID()生成一個UUID
loose-group_replication_group_name="aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa"
#訓示插件在伺服器啟動時不自動引導組操作
loose-group_replication_start_on_boot=OFF
件使用哪個ip:port與組中的其他成員進行内部通信。這裡的ip與端口不能與MySQL提供的ip:port 相同,如果使用相同ip則port必須不相同
loose-group_replication_local_address= "192.168.1.11:33061"
#設定組成員的主機名和端口
loose-group_replication_group_seeds= "192.168.1.11:33061,192.168.1.12:33061,192.168.1.13:33061"
#插件是否引導組,此選項隻能在任何時候在一個伺服器執行個體上使用,通常是第一次引導組時(或者在整個組關閉并重新備份的情況下)
loose-group_replication_bootstrap_group= off           

1.3 安裝啟動

每個伺服器是一個節點,都安裝好mysql

mysqld --defaults-file=/data1/my3306.cnf --datadir=/data1/mysql3306 --user=mysql3306 --initialize-insecure
mysqld --defaults-file=/data1/my3308.cnf --datadir=/data1/mysql3308 --user=mysql3308 --initialize-insecure           

啟動:

/usr/local/mysql-5.7.26/bin/mysqld_safe --defaults-file=/data1/mysql3306/my3306.cnf &
/usr/local/mysql-5.7.26/bin/mysqld_safe --defaults-file=/data1/mysql3308/my3308.cnf &           

1.4 安裝MGR插件,設定複制賬号(所有節點執行)

#無密碼登入
#安裝MGR插件
mysql> INSTALL PLUGIN group_replication SONAME 'group_replication.so';
#設定複制賬号
mysql> SET SQL_LOG_BIN=0;
mysql> CREATE USER repl@'%' IDENTIFIED BY 'repl';
mysql> GRANT REPLICATION SLAVE ON *.* TO repl@'%';
mysql> FLUSH PRIVILEGES;
mysql> SET SQL_LOG_BIN=1;
mysql> CHANGE MASTER TO MASTER_USER='repl', MASTER_PASSWORD='repl' FOR CHANNEL 'group_replication_recovery';           

1.5 啟動MGR單主模式

#主啟動(任選一個作為主庫,這裡選擇了1.11)
SET GLOBAL group_replication_bootstrap_group=ON;
START GROUP_REPLICATION;
SET GLOBAL group_replication_bootstrap_group=OFF;
mysql> SELECT * FROM performance_schema.replication_group_members;
#檢視MGR組資訊
+---------------------------+--------------------------------------+-------------+-------------+--------------+
| CHANNEL_NAME              | MEMBER_ID                            | MEMBER_HOST | MEMBER_PORT | MEMBER_STATE |
+---------------------------+--------------------------------------+-------------+-------------+--------------+
| group_replication_applier | 463679cf-7222-11e9-9459-000c29a6154a | vm1         |        3306 | ONLINE       |
+---------------------------+--------------------------------------+-------------+-------------+--------------+

#其他節點加入MGR,在從庫(1.12,1.13)上執行
mysql> START GROUP_REPLICATION;
mysql> SELECT * FROM performance_schema.replication_group_members;
+---------------------------+--------------------------------------+--------------+-------------+--------------+
| CHANNEL_NAME              | MEMBER_ID                            | MEMBER_HOST  | MEMBER_PORT | MEMBER_STATE |
+---------------------------+--------------------------------------+--------------+-------------+--------------+
| group_replication_applier | 0bbd0bcc-7223-11e9-a4fc-000c296aa366 | 192.168.1.12 |        3308 | ONLINE       |
| group_replication_applier | 18f64c9b-7223-11e9-bba2-000c293610f1 | 192.168.1.13 |        3308 | ONLINE       |
| group_replication_applier | 463679cf-7222-11e9-9459-000c29a6154a | 192.168.1.11 |        3306 | ONLINE       |
+---------------------------+--------------------------------------+--------------+-------------+--------------+

#查找主節點:
mysql> SHOW STATUS LIKE 'group_replication_primary_member';
+----------------------------------+--------------------------------------+
| Variable_name                    | Value                                |
+----------------------------------+--------------------------------------+
| group_replication_primary_member | 463679cf-7222-11e9-9459-000c29a6154a |
+----------------------------------+--------------------------------------+
或者 
select variable_value from performance_schema.global_status where variable_name = 'group_replication_primary_member';           

這個時候從是隻讀的,在上執行SQL會報錯:

ERROR 1290 (HY000): The MySQL server is running with the --super-read-only option so it cannot execute this statement           

2、多寫部署(單主切換到多主)

多主模式可以直接由單主模式切換, 需要在所有節點上先關閉組複制,設定 group_replication_single_primary_mode=OFF 等參數,再啟動組複制。

# 停止組複制(所有節點執行):
mysql> stop group_replication;
#單主模式設定為ON,多主模式設定為OFF
mysql> set global group_replication_single_primary_mode=OFF;
#在所有節點啟用多主資料更新的嚴格一緻性檢查
mysql> set global group_replication_enforce_update_everywhere_checks=ON;


# 随便選擇某個節點執行(這裡選擇之前是從節點的1.12執行)
mysql> SET GLOBAL group_replication_bootstrap_group=ON;
mysql> START GROUP_REPLICATION;
mysql> SET GLOBAL group_replication_bootstrap_group=OFF;

# 其他節點執行
mysql> START GROUP_REPLICATION;

mysql> SELECT * FROM performance_schema.replication_group_members;
+---------------------------+--------------------------------------+--------------+-------------+--------------+
| CHANNEL_NAME              | MEMBER_ID                            | MEMBER_HOST  | MEMBER_PORT | MEMBER_STATE |
+---------------------------+--------------------------------------+--------------+-------------+--------------+
| group_replication_applier | 0bbd0bcc-7223-11e9-a4fc-000c296aa366 | 192.168.1.12 |        3308 | ONLINE       |
| group_replication_applier | 18f64c9b-7223-11e9-bba2-000c293610f1 | 192.168.1.13 |        3308 | ONLINE       |
| group_replication_applier | 463679cf-7222-11e9-9459-000c29a6154a | 192.168.1.11 |        3306 | ONLINE       |
+---------------------------+--------------------------------------+--------------+-------------+--------------+

#多主模式,變量 group_replication_primary_member 為空(8.0版本會直接顯示MEMBER_ROLE)
mysql> SHOW STATUS LIKE 'group_replication_primary_member';
+----------------------------------+-------+
| Variable_name                    | Value |
+----------------------------------+-------+
| group_replication_primary_member |       |
+----------------------------------+-------+
可以測試寫入是多節點的           

3、多主切換到單主模式

# 所有節點執行
mysql> stop group_replication;
mysql> set global group_replication_enforce_update_everywhere_checks=OFF;
mysql> set global group_replication_single_primary_mode=ON;


# 主節點(192.168.1.11)執行
SET GLOBAL group_replication_bootstrap_group=ON;
START GROUP_REPLICATION;
SET GLOBAL group_replication_bootstrap_group=OFF;
# 從節點(192.168.1.12、192.168.1.13)執行
START GROUP_REPLICATION;           

三、節點加入

1.1 環境:(這裡是在多主模式下加入,單主模式下亦然)

因為MGR也是使用的GTID,是以新節點的加入也是需要通過備份和binlog來進行恢複,然後加入組複制的。這裡因為binlog都在,是以直接加入一個新安裝的MySQL執行個體加入到組裡。

MGR初探

1.2 新節點加入步驟

#新節點配置檔案:
loose-group_replication_local_address= "192.168.1.14:33061"
loose-group_replication_group_seeds= "192.168.1.11:33061,192.168.1.12:33061,192.168.1.13:33061,192.168.1.14:33061"

#在其他三個節點執行:
set global group_replication_group_seeds='192.168.1.11:33061,192.168.1.12:33061,192.168.1.13:33061,192.168.1.14:33061';

#新節點加入:
set global group_replication_single_primary_mode=OFF;
set global group_replication_enforce_update_everywhere_checks=ON;
CHANGE MASTER TO MASTER_USER='repl', MASTER_PASSWORD='repl' FOR CHANNEL 'group_replication_recovery';

#檢視所有節點:
mysql> SELECT * FROM performance_schema.replication_group_members;
+---------------------------+--------------------------------------+--------------+-------------+--------------+
| CHANNEL_NAME              | MEMBER_ID                            | MEMBER_HOST  | MEMBER_PORT | MEMBER_STATE |
+---------------------------+--------------------------------------+--------------+-------------+--------------+
| group_replication_applier | 0bbd0bcc-7223-11e9-a4fc-000c296aa366 | 192.168.1.12 |        3308 | ONLINE       |
| group_replication_applier | 18f64c9b-7223-11e9-bba2-000c293610f1 | 192.168.1.13 |        3308 | ONLINE       |
| group_replication_applier | 241b7e73-74d4-11e9-aef0-000c293af32c | 192.168.1.14 |        3308 | ONLINE       |
| group_replication_applier | 463679cf-7222-11e9-9459-000c29a6154a | 192.168.1.11 |        3306 | ONLINE       |
+---------------------------+--------------------------------------+--------------+-------------+--------------+           

到此新節點已經加入。

四、故障轉移

1、多主模式

MGR初探

第三部分新加入了節點的時候屬于多主模式,是以首先來看看,當多主模式下,有節點發生了故障會如何處理。

從圖中很容易看出來,一個節點fail了,寫線程直接連接配接到其他的節點上了,因為所有節點都是讀寫的,是以也就存在選取哪個為主節點了。

這裡直接将1.12這個節點的MySQL給kill掉,看看對組的影響:

#kill了1.12之後,很明顯這個節點直接被移出了
mysql> SELECT * FROM performance_schema.replication_group_members;
+---------------------------+--------------------------------------+--------------+-------------+--------------+
| CHANNEL_NAME              | MEMBER_ID                            | MEMBER_HOST  | MEMBER_PORT | MEMBER_STATE |
+---------------------------+--------------------------------------+--------------+-------------+--------------+
| group_replication_applier | 18f64c9b-7223-11e9-bba2-000c293610f1 | 192.168.1.13 |        3308 | ONLINE       |
| group_replication_applier | 241b7e73-74d4-11e9-aef0-000c293af32c | 192.168.1.14 |        3308 | ONLINE       |
| group_replication_applier | 463679cf-7222-11e9-9459-000c29a6154a | 192.168.1.11 |        3306 | ONLINE       |
+---------------------------+--------------------------------------+--------------+-------------+--------------+

#給叢集插入一些資料,再講kill的節點重新加入組裡
set global group_replication_single_primary_mode=OFF;
set global group_replication_enforce_update_everywhere_checks=ON;
START GROUP_REPLICATION;

可以發現新插入的資料同步到1.12節點了           

2、單主模式

MGR初探

單主模式存在一個選取哪個為新主的過程,大體過程為:

通過安裝字典順序(使用其UUID)來排序剩餘的server成員并選擇清單中第一個成員來作為下一個 主節點。           

先将多主模式切換到單主模式,檢視節點情況:

#按照官方文檔規則,單主模式下主fail了,應該是1.12這個server充當着
mysql> SELECT * FROM performance_schema.replication_group_members;
+---------------------------+--------------------------------------+--------------+-------------+--------------+
| CHANNEL_NAME              | MEMBER_ID                            | MEMBER_HOST  | MEMBER_PORT | MEMBER_STATE |
+---------------------------+--------------------------------------+--------------+-------------+--------------+
| group_replication_applier | 0bbd0bcc-7223-11e9-a4fc-000c296aa366 | 192.168.1.12 |        3308 | ONLINE       |
| group_replication_applier | 18f64c9b-7223-11e9-bba2-000c293610f1 | 192.168.1.13 |        3308 | ONLINE       |
| group_replication_applier | 241b7e73-74d4-11e9-aef0-000c293af32c | 192.168.1.14 |        3308 | ONLINE       |
| group_replication_applier | 463679cf-7222-11e9-9459-000c29a6154a | 192.168.1.11 |        3306 | ONLINE       |
+---------------------------+--------------------------------------+--------------+-------------+--------------+

mysql>  SHOW STATUS LIKE 'group_replication_primary_member';
+----------------------------------+--------------------------------------+
| Variable_name                    | Value                                |
+----------------------------------+--------------------------------------+
| group_replication_primary_member | 463679cf-7222-11e9-9459-000c29a6154a |
+----------------------------------+--------------------------------------+

#kill掉1.11這個主,看看哪個成為新的主
mysql> SELECT * FROM performance_schema.replication_group_members;
+---------------------------+--------------------------------------+--------------+-------------+--------------+
| CHANNEL_NAME              | MEMBER_ID                            | MEMBER_HOST  | MEMBER_PORT | MEMBER_STATE |
+---------------------------+--------------------------------------+--------------+-------------+--------------+
| group_replication_applier | 0bbd0bcc-7223-11e9-a4fc-000c296aa366 | 192.168.1.12 |        3308 | ONLINE       |
| group_replication_applier | 18f64c9b-7223-11e9-bba2-000c293610f1 | 192.168.1.13 |        3308 | ONLINE       |
| group_replication_applier | 241b7e73-74d4-11e9-aef0-000c293af32c | 192.168.1.14 |        3308 | ONLINE       |
+---------------------------+--------------------------------------+--------------+-------------+--------------+
#果然,1.12這台server成為了主
mysql> SHOW STATUS LIKE 'group_replication_primary_member';
+----------------------------------+--------------------------------------+
| Variable_name                    | Value                                |
+----------------------------------+--------------------------------------+
| group_replication_primary_member | 0bbd0bcc-7223-11e9-a4fc-000c296aa366 |
+----------------------------------+--------------------------------------+

#再要想加入1.11這台,按照之前加入節點的步驟就行了           

參考:

https://dev.mysql.com/doc/refman/5.7/en/group-replication.html

繼續閱讀