帶你走進MySQL全新高可用解決方案-MGR

vivo網際網路技術發表於2021-08-31

​一、初識MGR

相信很多人對MGR這個詞比較陌生,其實MGR(全稱 MySQL Group Replication 【MySQL 組複製】)是Oracle MySQL於2016年12月釋出MySQL 5.7.17推出的一個全新高可用和高擴充套件的解決方案。具備以下特性:

  • 高一致性,基於原生複製及Paxos協議的組複製技術,並以外掛的方式提供,提供一致資料安全保證;

  • 高容錯性,只要不是大多數節點壞掉就可以繼續工作,有自動檢測機制,當不同節點產生資源爭用衝突時,不會出現錯誤,按照先到者優先原則進行處理,並且內建了自動化腦裂防護機制;

  • 高擴充套件性,節點的新增和移除都是自動的,新節點加入後,會自動從其他節點上同步狀態,直到新節點和其他節點保持一致,如果某節點被移除了,其他節點自動更新組資訊,自動維護新的組資訊;

  • 高靈活性,有單主模式(圖1)和多主模式(圖2),單主模式下,會自動選主,所有更新操作都在主上進行;多主模式下,所有server都可以同時處理更新操作。

單主模式(圖1)

多主模式(圖2)

MGR架構圖如下所示:主要包括APIs層,元件層,負責協議模組和API+Paxos引擎層構成。

二、MGR技術演進

2.1 主從複製

傳統MySQL複製預設提供了一種簡單的主從複製方法,這種架構有一個主,以及一個或者多個從,當主節點執行提交事務,然後非同步的方式傳送到其他從節點,從庫重新執行relay log日誌內容達到主副本一致的目的,在預設情況下叢集所有節點資料都是一致的。

MySQL非同步複製

2.2  半同步複製

非同步複製存在一定的資料丟失風險,MySQL又在5.6版本中推出半同步複製,在同步資料協議中新增了一個同步操作,這樣意味主節點在commit操作,需要確認最少一個從節點確認接收到並且返回ACK,只有這樣主節點才能正確提交資料。

MySQL半同步複製

2.3  組複製

MySQL MGR 叢集最少3個server節點共同組成的分散式叢集,一種share-nothing複製方案,每個server節點都有完整的副本。

MySQL組複製協議

三、MGR技術特性

3.1 故障檢測

組複製自帶提供一種故障檢測機制,這個機制能報告哪個組成員是無響應的,並且如何判斷該成員是否排除叢集組。在組複製中故障檢測是一種分散式服務。假設伺服器A在預定時間段內未收到來自伺服器B的訊息,如果組內其他成員也同樣未收到來自伺服器B的訊息,那麼確認判斷B發生故障,這樣由其他成員判定將失聯組成員從叢集中剔除。

此時伺服器B與其他服務節點都無法聯絡。由於無法達成最小仲裁成員數,處於獨立狀態,無法對外提供服務。

3.2 容錯

MySQL組複製構建在Paxos分散式演算法基礎上實現的,以提供不同server之間的分散式協調。因此,它需要大多數server處於活動狀態以達到仲裁成員數,從而做出決定。這對系統可以容忍的不影響其自身及其整體功能的故障數量有直接影響。容忍f個故障所需的server數量(n)n = 2 * f + 1。

實踐中,這意味著為了容忍一個故障,組必須有三個server。如果一個伺服器故障, 仍然有兩個伺服器形成大多數(三分之二)來允許系統自動地繼續執行。但是,如果第二個server意外地宕掉,則該組鎖定(只有一個server),因為沒有達到多數可以達成選舉(不能自己選舉自己)。以下是說明上述公式的小表:

3.3  成員管理

組複製以組檢視(Group View,後續簡稱檢視)為基礎來進行成員管理,檢視一般在Group在一段時間內的成員狀態,如果這段時間沒有成員變化,也就是說沒有成員的加入和退出,一旦有成員加入或者退出組,則檢視就發生變化,並且使用檢視ID(view id)進行跟蹤變化區分先後時間,下面我們來看一張圖演示一下:

序號部分,初始化時,第一個檢視的序號從1開始,成員只有引導主一個,為進行初始化節點,以後出現的任何成員的加入和退出這個序號都需要增加1,可以通過performance_schema系統庫下的replication_group_member_stats表中查詢當前檢視。

四、MGR安裝體驗

瞭解任何一個新技術從部署開始,安裝比較簡單,我們準備如下測試節點:

10.10.1.214

10.10.1.217

10.10.6.91

安裝版本均為最新版本8.0.24,將安裝包解壓後進行初始化:

su - mysql
 
wget http://mirrors.ustc.edu.cn/mysql-ftp/Downloads/MySQL-8.0/mysql-8.0.24-linux-glibc2.12-x86_64.tar
 
tar -xf mysql-8.0.24-linux-glibc2.12-x86_64.tar
 
cd mysql-8.0.24-linux-glibc2.12-x86_64
 
# 建立配置檔案和資料目錄
 
mkdir conf data
 
初始化資料庫並且啟動
 
./bin/mysqld --initialize --datadir=/home/mysql/mysql-8.0.24-linux-glibc2.12-x86_64/data --basedir=/home/mysql/mysql-8.0.24-linux-glibc2.12-x86_64
 
./bin/mysqld_safe --defaults-file=conf/my.cnf &

4.1  通用配置說明

配置程式碼

[mysqld]
bind-address=0.0.0.0
datadir=/home/mysql/mysql-8.0.24-linux-glibc2.12-x86_64/data
basedir=/home/mysql/mysql-8.0.24-linux-glibc2.12-x86_64
port=3306
socket=/home/mysql/mysql-8.0.24-linux-glibc2.12-x86_64/data/mysqld.sock
user=mysql
# 每個節點要求不一樣
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
innodb_buffer_pool_size=1g
# 8.0 預設值XXHASH64,針對寫事務進行雜湊處理
transaction_write_set_extraction=XXHASH64
# 啟動載入組複製外掛
plugin_load_add='group_replication.so'
# 叢集唯一ID
group_replication_group_name="8d3cebd8-b132-11eb-8529-0242ac130003"
# 是否啟動MySQL服務時啟動組複製,建議值:off
group_replication_start_on_boot=off
# 本地IP後面埠33061可自定義,叢集通訊埠,建議統一埠
group_replication_local_address= "10.10.1.214:33061"
# 初始化叢集成員列表,可動態修改
group_replication_group_seeds= "10.10.1.214:33061,10.10.1.217:33061,10.10.6.91:33061"
# 判斷是否為引導組
group_replication_bootstrap_group=off
# 設定白名單,這裡特別注意,如果是同網段可以不用設定,如果是不同網段則需要修改否則通訊埠不可訪問
loose-group_replication_ip_whitelist='10.10.1.214,10.10.1.217,10.10.6.91'

4.2  單主模式部署

4.2.1  引導節點初始化

# 建立使用者和安裝外掛
 
mysql> SET SQL_LOG_BIN=0;
 
Query OK, 0 rows affected (0.00 sec) 
 
mysql> CREATE USER rpl_user@'%' IDENTIFIED BY 'password';
 
Query OK, 0 rows affected (0.01 sec) 
 
mysql> GRANT REPLICATION SLAVE ON *.* TO rpl_user@'%';
 
Query OK, 0 rows affected (0.00 sec) 
 
mysql> GRANT BACKUP_ADMIN ON *.* TO rpl_user@'%';
 
Query OK, 0 rows affected (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)
  
mysql> CHANGE REPLICATION SOURCE TO SOURCE_USER='rpl_user', SOURCE_PASSWORD='password' FOR CHANNEL 'group_replication_recovery';
 
Query OK, 0 rows affected, 2 warnings (0.05 sec)
  
mysql> INSTALL PLUGIN group_replication SONAME 'group_replication.so';
 
mysql> SHOW PLUGINS;
 
+---------------------------------+----------+--------------------+----------------------+---------+
 
| Name                            | Status   | Type               | Library              | License |
 
+---------------------------------+----------+--------------------+----------------------+---------+
 
| group_replication               | ACTIVE   | GROUP REPLICATION  | group_replication.so | GPL     |
 
+---------------------------------+----------+--------------------+----------------------+---------+
 
# 啟動引導節點
 
mysql> SET GLOBAL group_replication_bootstrap_group=ON;
 
Query OK, 0 rows affected (0.00 sec)
 
mysql> START GROUP_REPLICATION;
 
Query OK, 0 rows affected, 1 warning (2.33 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 | MEMBER_ROLE | MEMBER_VERSION |
 
+---------------------------+--------------------------------------+-------------------------------------------------+-------------+--------------+-------------+----------------+
 
| group_replication_applier | 4cf69361-b22b-11eb-a2c9-fa163ebefc6a | 10-10-1-214                                     |        3306 | ONLINE       | PRIMARY     | 8.0.24         |
 
+---------------------------+--------------------------------------+-------------------------------------------------+-------------+--------------+-------------+----------------+

4.2.2  加入從節點

mysql> SET SQL_LOG_BIN=0;
 
Query OK, 0 rows affected (0.00 sec)
 
mysql> CREATE USER rpl_user@'%' IDENTIFIED BY 'password';
 
Query OK, 0 rows affected (0.01 sec)
 
mysql> GRANT REPLICATION SLAVE ON *.* TO rpl_user@'%';
 
Query OK, 0 rows affected (0.03 sec) 
 
mysql> GRANT BACKUP_ADMIN ON *.* TO rpl_user@'%';
 
Query OK, 0 rows affected (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)
 
mysql> CHANGE REPLICATION SOURCE TO SOURCE_USER='rpl_user', SOURCE_PASSWORD='password' FOR CHANNEL 'group_replication_recovery';
 
Query OK, 0 rows affected, 2 warnings (0.05 sec)
 
mysql> START GROUP_REPLICATION;
 
Query OK, 0 rows affected, 1 warning (3.33 sec)
 
# 檢查狀態
 
mysql> SELECT * FROM performance_schema.replication_group_members;
 
+---------------------------+--------------------------------------+-------------------------------------------------+-------------+--------------+-------------+----------------+
 
| CHANNEL_NAME              | MEMBER_ID                            | MEMBER_HOST                                     | MEMBER_PORT | MEMBER_STATE | MEMBER_ROLE | MEMBER_VERSION |
 
+---------------------------+--------------------------------------+-------------------------------------------------+-------------+--------------+-------------+----------------+
 
| group_replication_applier | 4cf69361-b22b-11eb-a2c9-fa163ebefc6a | 10-10-1-214                                     |        3306 | ONLINE       | PRIMARY     | 8.0.24         |
 
| group_replication_applier | 53f39dba-b22b-11eb-bfdb-fa163e42784d | 10-10-1-217                                     |        3306 | ONLINE       | SECONDARY   | 8.0.24         |
 
+---------------------------+--------------------------------------+-------------------------------------------------+-------------+--------------+-------------+----------------+
 
2 rows in set (0.00 sec)
 
其他一個節點執行上述即可,執行完成後檢查
 
mysql> SELECT * FROM performance_schema.replication_group_members;
 
+---------------------------+--------------------------------------+-------------------------------------------------+-------------+--------------+-------------+----------------+
 
| CHANNEL_NAME              | MEMBER_ID                            | MEMBER_HOST                                     | MEMBER_PORT | MEMBER_STATE | MEMBER_ROLE | MEMBER_VERSION |
 
+---------------------------+--------------------------------------+-------------------------------------------------+-------------+--------------+-------------+----------------+
 
| group_replication_applier | 4cf69361-b22b-11eb-a2c9-fa163ebefc6a | 10-10-1-214                                     |        3306 | ONLINE       | PRIMARY     | 8.0.24         |
 
| group_replication_applier | 53f39dba-b22b-11eb-bfdb-fa163e42784d | 10-10-1-217                                     |        3306 | ONLINE       | SECONDARY     | 8.0.24         |
 
| group_replication_applier | 56779526-b22b-11eb-a28e-fa163e1f9809 | 10-10-6-91                                      |        3306 | ONLINE       | SECONDARY     | 8.0.24         |
 
+---------------------------+--------------------------------------+-------------------------------------------------+-------------+--------------+-------------+----------------+
 
3 rows in set (0.00 sec)

4.3  多主模式部署

多主模式和單主部署方式差不多,只在加入叢集時多執行:

set global group_replication_single_primary_mode=off;

單主的都是ON。

4.3.1  引導節點初始化

mysql> set global group_replication_single_primary_mode=off;
 
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> start group_replication;
 
Query OK, 0 rows affected, 1 warning (2.16 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 | MEMBER_ROLE | MEMBER_VERSION |
 
+---------------------------+--------------------------------------+-------------------------------------------------+-------------+--------------+-------------+----------------+
 
| group_replication_applier | 4cf69361-b22b-11eb-a2c9-fa163ebefc6a | 10-10-1-214                                     |        3306 | ONLINE       | PRIMARY     | 8.0.24         |
 
+---------------------------+--------------------------------------+-------------------------------------------------+-------------+--------------+-------------+----------------+
 
1 row in set (0.00 sec)

4.3.2  加入其他節點

mysql> set global group_replication_single_primary_mode=off;
 
Query OK, 0 rows affected (0.00 sec) 
 
mysql> START GROUP_REPLICATION;
 
Query OK, 0 rows affected, 1 warning (3.26 sec)
 
mysql> select * from  performance_schema.replication_group_members;
 
+---------------------------+--------------------------------------+-------------------------------------------------+-------------+--------------+-------------+----------------+
 
| CHANNEL_NAME              | MEMBER_ID                            | MEMBER_HOST                                     | MEMBER_PORT | MEMBER_STATE | MEMBER_ROLE | MEMBER_VERSION |
 
+---------------------------+--------------------------------------+-------------------------------------------------+-------------+--------------+-------------+----------------+
 
| group_replication_applier | 4cf69361-b22b-11eb-a2c9-fa163ebefc6a | 10-10-1-214                                     |        3306 | ONLINE       | PRIMARY     | 8.0.24         |
 
| group_replication_applier | 53f39dba-b22b-11eb-bfdb-fa163e42784d | 10-10-1-217                                     |        3306 | ONLINE       | PRIMARY     | 8.0.24         |
 
| group_replication_applier | 56779526-b22b-11eb-a28e-fa163e1f9809 | 10-10-6-91                                      |        3306 | ONLINE       | PRIMARY     | 8.0.24         |
 
+---------------------------+--------------------------------------+-------------------------------------------------+-------------+--------------+-------------+----------------+
 
3 rows in set (0.00 sec)

4.4  測試體驗

# 在任意節點執行
 
mysql> show databases;
 
+--------------------+
 
| Database           |
 
+--------------------+
 
| information_schema |
 
| mysql              |
 
| performance_schema |
 
| sys                |
 
+--------------------+
 
4 rows in set (0.00 sec) 
 
mysql> create database test;
 
Query OK, 1 row affected (0.01 sec)
  
# 任意節點查詢
mysql> show databases;
 
+--------------------+
 
| Database           |
 
+--------------------+
 
| information_schema |
 
| mysql              |
 
| performance_schema |
 
| sys                |
 
| test               |
 
+--------------------+
 
5 rows in set (0.00 sec)

五、應用場景

  • MGR採用多副本模式,在2N+1個叢集中,叢集只要N+1個節點還存活,資料庫就能穩定對外提供服務,適用於金融場景,因為這些場景資料必須零丟失,可用性在4個9甚至5個9。

  • 適用於替代當前主從高可用版本,解決單點寫入問題。

  • 針對業務需要彈性擴充套件節點的基礎架構環境,例如私有云。

六、總結

儘管MySQL在2016年就推出了MGR該功能,同時我們也知道有很多好處,並且有大膽的公司採用進行測試甚至部署線上環境,據公開資料網易、滴滴都有使用,國內部分商業銀行也有使用,但仍然有不少人處於觀望狀態,主要有以下幾點原因導致:

需求不是特別強烈

  • 很多業務情況使用MySQL半同步和非同步複製足夠滿足業務要求,配合MHA第三方元件滿足了絕大部分場景需求。

分散式新事物

  • 本身分散式這個概念已經存在多年,但是由於MGR推出年限較短,且我們搜尋官方bug庫任然存在較多未解決的bug。使用者使用排查問題較為困難,且由於分散式設計導致問題復現難也是一種阻礙。

生態不成熟

  • 官方几乎沒有完全成熟用來構建整套高可用架構的解決方案,如果想要大規模使用還是需要更加成熟的生態。

任何新鮮事物都有一個被大眾接受過程,只是需要時間篩選和磨礪。

參考文件

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

作者:vivo網際網路資料庫團隊-Liu Shilin

相關文章