一、初識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