MySQL MGR 高可用集群搭建過程詳解
1、MGR 前置介紹
阿里云RDS集群方案用的就是MGR模式!

1.1、什么是 MGR
- MGR(MySQL Group Replication)是MySQL 5.7.17版本誕生的,是MySQL自帶的一個插件,可以靈活部署。
- 保證數(shù)據(jù)一致性又可以自動切換,具備故障檢測功能、支持多節(jié)點寫入。
- 集群是多個MySQL Server節(jié)點共同組成的分布式集群,每個Server都有完整的副本,它是基于ROW格式的二進制日志文件和GTID特性。
1.2、MGR 優(yōu)點
- 強一致性:基于原生復(fù)制及paxos協(xié)議的組復(fù)制技術(shù),并以插件的方式提供,提供一致數(shù)據(jù)安全保證。
- 高容錯性:只要不是大多數(shù)節(jié)點壞掉就可以繼續(xù)工作,有自動檢測機制,當(dāng)不同節(jié)點產(chǎn)生資源爭用沖突時,不會出現(xiàn)錯誤,按照先到者優(yōu)先原則進行處理,并且內(nèi)置了自動化腦裂防護機制。
- 高擴展性:節(jié)點的新增和移除都是自動的,新節(jié)點加入后,會自動從其他節(jié)點上同步狀態(tài),直到新節(jié)點和其他節(jié)點保持一致,如果某節(jié)點被移除了,其他節(jié)點自動更新組信息,自動維護新的組信息。
- 高靈活性:有單主模式和多主模式。單主模式下,會自動選主,所有更新操作都在主上進行;多主模式下,所有server都可以同時處理更新操作。工作中優(yōu)先使用單主模式!
1.3、MGR 缺點
- 僅支持InnoDB表,并且每張表一定要有一個主鍵,用于做write set的沖突檢測。
- 必須打開GTID特性,二進制日志格式必須設(shè)置為ROW,用于選主與write set;主從狀態(tài)信息存于表中(–master-info-repository=TABLE 、–relay-log-inforepository=TABLE),–log-slave-updates打開。
- MGR不支持大事務(wù),事務(wù)大小最好不超過143MB,當(dāng)事務(wù)過大,無法在5秒的時間內(nèi)通過網(wǎng)絡(luò)在組成員之間復(fù)制消息,則可能會懷疑成員失敗了,然后將其驅(qū)逐出局。
- 目前一個MGR集群最多支持9個節(jié)點。
- 不支持外鍵于save point特性,無法做全局間的約束檢測與部分事務(wù)回滾。
- 二進制日志不支持Binlog Event Checksum。
1.4、MGR 適用場景
- 金融交易、重要數(shù)據(jù)存儲、對主從一致性要求高的場景。
- 核心數(shù)據(jù)總量未過億。
- 讀多寫少,如:互聯(lián)網(wǎng)電商。
2、MySQL MGR 搭建流程
2.1、環(huán)境準(zhǔn)備
本次集群搭建,我使用3臺阿里云ECS服務(wù)器(CentOS 7.9,2核2G,20G硬盤),每臺服務(wù)器都分配公網(wǎng)IP,開放安全組:22(SSH)、3306(MySQL)、24901(MGR)。我的服務(wù)器配置如下:
Master服務(wù)器(hostname:n0):172.21.180.98
Slave服務(wù)器1(hostname:n1):172.21.180.99
Slave服務(wù)器2(hostname:n2):172.21.180.100

2.2、搭建流程
2.2.1、配置系統(tǒng)環(huán)境
將Hosts文件寫入n0/n1/n2節(jié)點與內(nèi)網(wǎng)IP對應(yīng)關(guān)系,后面配置采用域名訪問:
# 3臺服務(wù)器都執(zhí)行 sudo cat > /etc/hosts <<-'EOF' 172.21.180.98 n0 172.21.180.99 n1 172.21.180.100 n2 EOF
分別為三臺服務(wù)器依次設(shè)置主機名稱,三臺服務(wù)器執(zhí)行命令:
# 第1臺服務(wù)器 hostnamectl set-hostname n0 # 第2臺服務(wù)器 hostnamectl set-hostname n1 # 第3臺服務(wù)器 hostnamectl set-hostname n2
2.2.2、安裝 MySQL
下載 MySQL 官方Y(jié)UM倉庫源(這個并不是安裝MySQL):
# 3臺服務(wù)器都執(zhí)行 cd /home/ wget --no-check-certificate https://repo.mysql.com/mysql80-community-release-el7-5.noarch.rpm yum localinstall -y mysql80-community-release-el7-5.noarch.rpm
修改倉庫配置,將下圖中g(shù)pgcheck置為0:
vi /etc/yum.repos.d/mysql-community.repo

安裝 MySQL 8.0.26:
# 3臺服務(wù)器都執(zhí)行 yum install -y mysql-community-server-8.0.26
2.2.3、配置啟動 MySQL
主節(jié)點n0執(zhí)行:直接CV就行,不要墨跡!
# 修改 MySQL 配置 sudo cat >> /etc/my.cnf <<-'EOF' # 使用mysql_native_password密碼策略,防止navicat連不上mysql8 default_authentication_plugin=mysql_native_password # 設(shè)置MySQL插件目錄:MGR基于插件,必須設(shè)置插件路徑 plugin_dir=/usr/lib64/mysql/plugin # 服務(wù)器編號,Master=1 server_id=1 # 開啟binlog的GTID模式(MGR強制要求) gtid_mode=ON # 開啟后MySQL只允許能夠保障事務(wù)安全,并且能夠被日志記錄的SQL語句被執(zhí)行 enforce_gtid_consistency=ON # 關(guān)閉binlog校驗(MGR強制要求) binlog_checksum=NONE # 定義用于事務(wù)期間哈希寫入提取的算法,組復(fù)制模式下必須設(shè)置為 XXHASH64。 transaction_write_set_extraction=XXHASH64 # 確定組復(fù)制恢復(fù)時是否應(yīng)該應(yīng)用 SSL,通常設(shè)置為“開”,但默認設(shè)置為“關(guān)”。 loose-group_replication_recovery_use_ssl=ON # 服務(wù)器實例所在復(fù)制組名稱,必須是有效的 UUID,所有節(jié)點必須相同。 loose-group_replication_group_name="bbbbbbbb-bbbb-cccc-dddd-eeeeeeeeeeee" # 確定服務(wù)器是否應(yīng)該在服務(wù)器啟動期間啟動組復(fù)制。 loose-group_replication_start_on_boot=OFF # 為復(fù)制組中其他的成員提供的網(wǎng)絡(luò)地址,指定為“主機:端口”的格式化字符串。 # 很多人想當(dāng)然認為端口應(yīng)該是3306,起始不然,MGR需要開啟新端口24901同步交換 # 所以這里不要寫錯,同時,前面我們配置了hosts文件做了主機名與IP的映射,這里直接寫主機名即可 loose-group_replication_local_address="n0:24901" # 用于建立新成員到組的連接組成員列表。 # 這個列表指定為由分隔號間隔的組成員網(wǎng)絡(luò)地址列表,類似 host1:port1、host2:port2 的格式。 # 同樣采用n0~n2的主機名替代 loose-group_replication_group_seeds="n0:24901,n1:24901,n2:24901" # 配置此服務(wù)器為引導(dǎo)組,這個選項必須僅在一臺服務(wù)器上設(shè)置, # 并且僅當(dāng)?shù)谝淮螁咏M或者重新啟動整個組時。成功引導(dǎo)組啟動后,將此選項設(shè)置為關(guān)閉。 loose-group_replication_bootstrap_group=OFF EOF
從節(jié)點n1執(zhí)行:直接CV就行,不要墨跡!
sudo cat >> /etc/my.cnf <<-'EOF' default_authentication_plugin=mysql_native_password plugin_dir=/usr/lib64/mysql/plugin # 設(shè)置唯一的服務(wù)器編號 server_id=2 gtid_mode=ON enforce_gtid_consistency=ON binlog_checksum=NONE # 這個參數(shù)決定primary節(jié)點到secondary節(jié)點的請求是否為基于 RSA 密鑰對的密碼交換所需的公鑰 loose-group_replication_recovery_get_public_key=ON loose-group_replication_recovery_use_ssl=ON loose-group_replication_group_name="bbbbbbbb-bbbb-cccc-dddd-eeeeeeeeeeee" loose-group_replication_start_on_boot=OFF # 設(shè)置本機地址n1:24901 loose-group_replication_local_address="n1:24901" loose-group_replication_group_seeds="n0:24901,n1:24901,n2:24901" loose-group_replication_bootstrap_group=OFF EOF
從節(jié)點n2執(zhí)行:直接CV就行,不要墨跡!
sudo cat >> /etc/my.cnf <<-'EOF' default_authentication_plugin=mysql_native_password plugin_dir=/usr/lib64/mysql/plugin #設(shè)置唯一的服務(wù)器編號 server_id=3 gtid_mode=ON enforce_gtid_consistency=ON binlog_checksum=NONE #這個參數(shù)決定primary節(jié)點到secondary節(jié)點的請求是否為基于 RSA 密鑰對的密碼交換所需的公鑰 loose-group_replication_recovery_get_public_key=ON loose-group_replication_recovery_use_ssl=ON loose-group_replication_group_name="bbbbbbbb-bbbb-cccc-dddd-eeeeeeeeeeee" loose-group_replication_start_on_boot=OFF #設(shè)置本機地址n2:24901 loose-group_replication_local_address="n2:24901" loose-group_replication_group_seeds="n0:24901,n1:24901,n2:24901" loose-group_replication_bootstrap_group=OFF EOF
三臺服務(wù)器,依次啟動 MySQL
# 3臺服務(wù)器都執(zhí)行 systemctl start mysqld
2.2.4、修改密碼、設(shè)置主從同步
三臺服務(wù)器,依次通過該命令,獲取數(shù)據(jù)庫連接密碼:
# 獲取數(shù)據(jù)庫密碼 grep 'temporary password' /var/log/mysqld.log
三臺服務(wù)器,連接到數(shù)據(jù)庫控制臺中:
# 連接數(shù)據(jù)庫 mysql -uroot -p'密碼'
三臺數(shù)據(jù)庫控制臺中,都執(zhí)行下述命令(3臺服務(wù)器都執(zhí)行):
# 修改root密碼為asAS123456! ALTER USER 'root'@'localhost' IDENTIFIED WITH mysql_native_password BY 'asAS123456!'; # 創(chuàng)建rpl_user賬戶,此賬戶用于實現(xiàn)主從數(shù)據(jù)同步 CREATE USER rpl_user@'%' IDENTIFIED BY 'asAS123456!'; # 賦予主從同步權(quán)限 GRANT REPLICATION SLAVE ON *.* TO rpl_user@'%'; # 創(chuàng)建一個遠程連接用戶,這個用戶用在Navcate、JDBC登錄的時候,直接用root登錄不好 create user 'remote'@'%' identified with mysql_native_password by 'asAS123456!'; # 為remote用戶賦予所有數(shù)據(jù)庫資源的訪問權(quán)限,熟悉grant的小伙伴可以自己調(diào)整 grant all privileges on *.* to remote@'%'; # 讓剛才的修改生效 FLUSH PRIVILEGES; # 刪除已產(chǎn)生的Binlog # 一定要RESET MASTER,它會刪除剛才已產(chǎn)生的Binlog # 因為剛才Binglog包含創(chuàng)建用戶這種高權(quán)限操作,用于主從同步的rpl_user賬戶是沒有權(quán)限執(zhí)行的 # 這就會導(dǎo)致RelayLog重放無法正確執(zhí)行,導(dǎo)致從屬服務(wù)器卡死在"RECEVERING"狀態(tài) # 利用RESET MASTER刪除這些無法執(zhí)行的binlog,就沒問題了 RESET MASTER;
2.2.5、安裝 MGR 插件
在三臺服務(wù)器的MySQL控制臺中,安裝MGR插件,執(zhí)行命令:
# 3臺服務(wù)器都執(zhí)行 INSTALL PLUGIN group_replication SONAME 'group_replication.so';
在主服務(wù)器的MySQL控制臺上,執(zhí)行下述命令:
# 注意:只在主服務(wù)器上運行 # 我們在 primary.cnf 配置文件中把 group_replication_bootstrap_group 參數(shù)設(shè)置成 OFF # 在 primary 服務(wù)器啟動時并不會直接啟動復(fù)制組,通過下面的命令動態(tài)的開啟復(fù)制組是我們的集群更安全 SET GLOBAL group_replication_bootstrap_group=ON; START GROUP_REPLICATION; SET GLOBAL group_replication_bootstrap_group=OFF;
在兩個從服務(wù)器MySQL控制臺上,執(zhí)行下述命令:
# 指定主從賬戶與指定通信頻道 CHANGE MASTER TO MASTER_USER="rpl_user", MASTER_PASSWORD="asAS123456!" FOR CHANNEL 'group_replication_recovery'; # 開啟組網(wǎng)數(shù)據(jù)同步 START GROUP_REPLICATION;
當(dāng)兩個從節(jié)點都運行完畢后,運行下面SQL結(jié)果進行驗證:
SELECT * FROM performance_schema.replication_group_members;
出現(xiàn)以下情況,每個節(jié)點都是ONLINE狀態(tài),說明集群搭建成功:

3、MySQL MGR 故障轉(zhuǎn)移
上面已經(jīng)將MySQL MGR集群搭建完畢,并且節(jié)點都是ONLINE狀態(tài)。

3.1、主節(jié)點n0下線,重新選舉
首先,在主服務(wù)器n0上執(zhí)行停止mysql命令,如下:
systemctl stop mysqld;
此時,在從節(jié)點n1查看集群狀態(tài)發(fā)現(xiàn),n1被選舉為主節(jié)點:

這是由于MGR集群選舉策略為:
- 優(yōu)先低版本節(jié)點
- 版本一樣,優(yōu)先權(quán)重大的節(jié)點
- 版本與權(quán)重一樣,按照 server uuid 的字母順序選主
在n1從節(jié)點上,通過命令查看故障轉(zhuǎn)移日志:
# 查看MySQL日志 tail -n 50 /var/log/mysqld.log
n1日志解析如下:
# n0:3306(主節(jié)點n0)從組中被移除掉 [Warning] [MY-011499] [Repl] Plugin group_replication reported: 'Members removed from the group: n0:3306' # 重新選舉新的 Primary 主節(jié)點 [System] [MY-011500] [Repl] Plugin group_replication reported: 'Primary server with address n0:3306 left the group. Electing new Primary.' # n1:3306(從節(jié)點n1)被選舉為主節(jié)點,執(zhí)行之前未完成的事務(wù)處理 [System] [MY-011507] [Repl] Plugin group_replication reported: 'A new primary with address n1:3306 was elected. The new primary will execute all previous group transactions before allowing writes.' # 組成員目前只剩 n1:3306, n2:3306 [System] [MY-011503] [Repl] Plugin group_replication reported: 'Group membership changed to n1:3306, n2:3306 on view 17172171443362674:4.' # 關(guān)閉 n1 節(jié)點的只讀狀態(tài) [System] [MY-013731] [Repl] Plugin group_replication reported: 'The member action "mysql_disable_super_read_only_if_primary" for event "AFTER_PRIMARY_ELECTION" with priority "1" will be run.' # 設(shè)置 super_read_only=OFF [System] [MY-011566] [Repl] Plugin group_replication reported: 'Setting super_read_only=OFF.' # 當(dāng)前節(jié)點(n1)以主節(jié)點身份工作 [System] [MY-011510] [Repl] Plugin group_replication reported: 'This server is working as primary member.'
在n2從節(jié)點上,通過命令查看故障轉(zhuǎn)移日志:
# 查看MySQL日志 tail -n 50 /var/log/mysqld.log
n2日志解析如下:
# n0:3306(主節(jié)點n0)從組中被移除掉 [Warning] [MY-011499] [Repl] Plugin group_replication reported: 'Members removed from the group: n0:3306' # 重新選舉新的 Primary 主節(jié)點 [System] [MY-011500] [Repl] Plugin group_replication reported: 'Primary server with address n0:3306 left the group. Electing new Primary.' # n1:3306(從節(jié)點n1)被選舉為主節(jié)點,執(zhí)行之前未完成的事務(wù)處理 [System] [MY-011507] [Repl] Plugin group_replication reported: 'A new primary with address n1:3306 was elected. The new primary will execute all previous group transactions before allowing writes.' # 組成員目前只剩 n1:3306, n2:3306 [System] [MY-011503] [Repl] Plugin group_replication reported: 'Group membership changed to n1:3306, n2:3306 on view 17172171443362674:4.' # 當(dāng)前節(jié)點(n2)作為主節(jié)點(n1)的從成員身份工作 [System] [MY-011511] [Repl] Plugin group_replication reported: 'This server is working as secondary member with primary member address n1:3306.'
3.2、新主節(jié)點n1下線,集群不可用
當(dāng)在新晉升的主節(jié)點n1上執(zhí)行停止MySQL操作:
systemctl stop mysqld;
此時,在n2上通過命令查看發(fā)現(xiàn),n1主節(jié)點盡管已經(jīng)下線,但n2查看集群狀態(tài)時還在顯示,因為只有1個節(jié)點的情況下,少于n/2+1的規(guī)則,導(dǎo)致整體 MGR 集群失效,n2節(jié)點無法產(chǎn)生重新選舉,同時n2的日志也不會有任何新內(nèi)容產(chǎn)生:
SELECT * FROM performance_schema.replication_group_members;

3.3、恢復(fù) MGR 集群
恢復(fù)流程很簡單,先將三臺服務(wù)器的MySQL各自重啟:
# 3臺服務(wù)器都執(zhí)行 systemctl restart mysqld;
然后重復(fù)執(zhí)行 2.2.4 ~ 2.2.5 章節(jié)流程即可恢復(fù) MGR 集群。
4、單主模式和多主模式
4.1、模式介紹
4.1.1、單主模式
在單主模式下, 組復(fù)制具有自動選主功能,每次只有一個 server成員可以作為主節(jié)點。
單主模式 group 內(nèi)只有一臺節(jié)點可寫可讀,其他節(jié)點只可以讀。對于group的部署,需要先跑起primary主節(jié)點,然后再跑起其他的節(jié)點,并把這些節(jié)點加進group。其他的節(jié)點就會自動同步primary節(jié)點上面的變化,然后將自己設(shè)置為只讀模式。
當(dāng)primary主節(jié)點意外宕機或者下線,在滿足大多數(shù)節(jié)點存活的情況下,group內(nèi)部發(fā)起選舉,選出下一個可用的讀節(jié)點,提升為primary節(jié)點。

4.1.2、多主模式
在多主模式下,所有的 MySQL 節(jié)點都可以同時接受讀寫操作。group內(nèi)的所有節(jié)點都是primary主節(jié)點,同時可以進行讀寫操作,并且數(shù)據(jù)是最終一致的。

4.2、模式切換
之前我們搭建的 MySQL MGR 集群就是單主模式(默認),那么如何切換為多主模式呢?按照如下操作進行。
4.2.1、單主 ——> 多主
從 n0 ~ n2 停止組復(fù)制,開啟多主模式(3個節(jié)點都執(zhí)行):
# 停止組復(fù)制 stop group_replication; # 是否啟用單主模式,默認ON,OFF代表多主 set global group_replication_single_primary_mode=OFF; # 是否開啟條件檢查,因為多主的約束更為嚴(yán)格,不符合要求的直接拒絕 # 不支持外鍵的級聯(lián)操作 # 不支持“串行化Serializable” set global group_replication_enforce_update_everywhere_checks=ON;
在 n0 主節(jié)點啟用組復(fù)制:
# 只在 n0 上執(zhí)行 SET GLOBAL group_replication_bootstrap_group=ON; START GROUP_REPLICATION; SET GLOBAL group_replication_bootstrap_group=OFF;
在 n1,n2 節(jié)點上啟用組復(fù)制:
# 只在 n1, n2 上執(zhí)行 START GROUP_REPLICATION;
此時,可以看到三臺MySQL都是主節(jié)點:
SELECT * FROM performance_schema.replication_group_members;

4.2.2、多主 ——> 單主
從 n0 ~ n2 停止組復(fù)制,開啟多主模式(3個節(jié)點都執(zhí)行):
# 停止組復(fù)制 stop group_replication; # 是否開啟條件檢查,因為多主的約束更為嚴(yán)格,不符合要求的直接拒絕 # 不支持外鍵的級聯(lián)操作 # 不支持“串行化Serializable” set global group_replication_enforce_update_everywhere_checks=OFF; # 是否啟用單主模式,默認ON,OFF代表多主 set global group_replication_single_primary_mode=ON;
在 n0 主節(jié)點啟用組復(fù)制:
# 只在 n0 上執(zhí)行 SET GLOBAL group_replication_bootstrap_group=ON; START GROUP_REPLICATION; SET GLOBAL group_replication_bootstrap_group=OFF;
在 n1,n2 節(jié)點上啟用組復(fù)制:
# 只在 n1, n2 上執(zhí)行 START GROUP_REPLICATION;
此時,可以看到三臺MySQL變成了主從模式:
SELECT * FROM performance_schema.replication_group_members;

到此這篇關(guān)于MySQL MGR 高可用集群搭建過程詳解的文章就介紹到這了,更多相關(guān)mysql mgr高可用集群內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
MySQL中用戶授權(quán)以及刪除授權(quán)的方法
這篇文章主要介紹了MySQL中用戶授權(quán)以及刪除授權(quán)的方法的相關(guān)資料,需要的朋友可以參考下2015-12-12
mysql數(shù)據(jù)插入覆蓋和時間戳的問題及解決
這篇文章主要介紹了mysql數(shù)據(jù)插入覆蓋和時間戳的問題及解決,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-03-03

