天天看點

實戰篇:MySQL高可用--MGR實戰

MGR特點

(1)基于Paxos協定和原生複制,多數節點同意即可通過事務送出

(2)具備高可用自動故障檢測,可自動切換

(3)可彈性擴充,叢集自動的新增和移除節點

(4)有單主和多主模式

(5)支援多節點寫入,具備沖突檢測機制,可以适應多種應用場景需求

MGR組複制是什麼

(1)主從複制是異步複制

master事務的送出不需要經過slave的确認,slave是否接收到master的binlog,master并不care。slave接收到master binlog後先寫relay log,最後異步地去執行relay log中的sql應用到自身。由于master的送出不需要確定slave relay log是否被正确接受,當slave接受master binlog失敗或者relay log應用失敗,master無法感覺。

實戰篇:MySQL高可用--MGR實戰

(2)半同步複制

基于傳統異步存在的缺陷,mysql在5.5版本推出半同步複制。可以說半同步複制是傳統異步複制的改進,在master事務的commit之前,必須確定一個slave收到relay log并且響應給master後(從庫收到并産生 relaylog 後會向主庫發送一個 ACK 的資訊包,當主庫獲得這個包後,認為從庫已經獲得 relaylog)才能進行事務的commit。但是slave對于relay log的應用仍然是異步進行的。

實戰篇:MySQL高可用--MGR實戰

(3)組複制

基于傳統異步複制和半同步複制的缺陷——資料的一緻性問題無法保證,MySQL官方在5.7.17版本正式推出組複制(MySQL Group Replication,簡稱MGR)。

由若幹個節點共同組成一個複制組,一個事務的送出,必須經過組内大多數節點(N / 2 + 1)決議并通過,才能得以送出。如上圖所示,由3個節點組成一個複制組,Consensus層為一緻性協定層,在事務送出過程中,發生組間通訊,由2個節點決議(certify)通過這個事務,事務才能夠最終得以送出并響應。

引入組複制,主要是為了解決傳統異步複制和半同步複制可能産生資料不一緻的問題。組複制依靠分布式一緻性協定(Paxos協定的變體),實作了分布式下資料的最終一緻性,提供了真正的資料高可用方案(是否真正高可用還有待商榷)。其提供的多寫方案,給我們實作多活方案帶來了希望。

實戰篇:MySQL高可用--MGR實戰

組複制脫離了傳統的主從模式結構,是一個具有容錯功能的叢集架構,在組複制的架構中,有多個 server成員構成,并且每個成員都可以獨立執行事務,也就意味着多寫的功能,但是所有的讀寫事務必須在沖突校驗完成後才能送出,如果是隻讀型的事務那麼會直接送出。當某個節點上發出一個讀寫的事務準備送出時,那麼這個節點就會向整個叢集開始廣播這次讀寫的變更和對應的一個校驗辨別符,然後會針對這個事務産生一個全局的順序号,由于是有順序号的,是以叢集中的每個成員都會按照順序去執行事務的變更進而保證了資料的一緻性。

如果在不同的 server 上執行了相同的操作,并且産生了事務沖突,那麼校驗機制就會做成相應的判斷,通常先送出的事務先執行,後送出的復原。是以從某種程度上來說,組複制是一種僞同步複制模式。

組複制的模式

(1)單主模式

在單主模式下,組有一個設定為讀寫模式的單主 server。 組中的所有其他成員被自動設定為隻讀模式(超級隻讀模式)。主伺服器通常是用于引導組的第一個 server,所有其他加入的 server 自動從主伺服器同步并設定為隻讀。

實戰篇:MySQL高可用--MGR實戰

在單主機模式下,将禁用在多主機模式下部署的某些檢查,因為系統會強制在組中每次隻有一個寫入server。 例如,在單主模式下允許對具有外鍵的表進行更改,而在多主模式下不允許。 在主伺服器故障時,自動選主機制選擇下一個主伺服器。 通過按字典順序(使用其 UUID)來排序剩餘的 server 成員并選擇清單中的第一個成員來作為下一個主伺服器。

如果主伺服器從組中移除,則啟動主節點選擇程式,然後從組中的其餘 server 成員中選擇新的主節點。通過檢視新視圖,按照詞典順序将 server 的 UUID 進行排序并選擇第一個作為主節點。選擇了新的主節點後,它将自動設定為隻讀,其他輔助節點仍然為輔助節點,是以也是隻讀。

(2)多主模式

多主模式,也就是所有節點都可以寫入,每個節點基本都一樣

實戰篇:MySQL高可用--MGR實戰

PXC和MGR的差別

(1)執行送出PXC 事務需要在所有節點跑一下

MGR 多數節點同意,即可執行

(2)複制

PXC 在複制上需要Gcache中緩存

MGR 直接寫binlog

(3)新增節點

新增節點PXC支援mysqldump xtrabackup

MGR直接內建複制克隆

(4)網絡中斷

網絡中斷發生時,PXC具有分區的表不可讀寫

MGR 可讀不可寫

(5)流控

MGR 寫入變慢

PXC所有節點不可寫

(6)跨平台

跨平台;PXC支援Linux

MGR支援所有平台(7)DDL當PXC在進行DDL時,為了保證節點資料一緻,此時整個叢集拒絕寫操作,注意是叢集内所有的表寫操作均無法提供寫服務,但是讀操作可以正常進行。MGR 采用innodb存儲引擎,支援線上DDL

單主多主模式搭建

單主搭建(5.7)

規劃主機

我這裡用三台虛拟機

192.168.168.101 3306

192.168.168.102 3306

192.168.168.103 3306

(1)配置host和IP的映射

在三台主機上分别 vi /etc/hosts

mysql 的組複制依然存在解析 host 的 bug,是以我們必須在所有節點内把 host和 ip 的映射關系配置完畢。

192.168.168.101 master1

192.168.168.102 slave2

192.168.168.103 slave3

實戰篇:MySQL高可用--MGR實戰

(2)關閉防火牆

檢視centos7的防火牆

firewall-cmd --state

停止firewall

systemctl stop firewalld.service

禁止firewall開機啟動

systemctl disable firewalld.service

實戰篇:MySQL高可用--MGR實戰

(3)快速初始化3台mysql庫

1、壓縮包解壓

tar -xvf mysql-5.7.21-linux-glibc2.12-x86_64.tar.gz

mv mysql-5.7.21-linux-glibc2.12-x86_64.tar.gz /usr/local/mysql

2、配置環境變量

vi /etc/profile

export PATH=/usr/local/mysql/bin:$PATH

source /etc/profile

3、編輯mysql配置檔案

vi /etc/my.cnf

[mysqld]

user=mysql

basedir=/usr/local/mysql

datadir=/data/3306/data

log_bin=/data/3306/binlog/mysql-bin

port=3306

server_id=1013306 #(另外兩台機器 server_id=1023306\ server_id=1033306)

socket=/tmp/mysql.sock

gtid-mode=on

enforce-gtid-consistency=true

log_slave_updates=1

relay_log_info_repository=TABLE

master_info_repository=TABLE

relay_log_recovery=on

4、建立資料目錄和賦權

mkdir -p /data/3306/data

mkdir -p /data/3306/binlog

chown mysql:mysql -R /data

5、初始化

mysqld --defaults-file=/etc/my.cnf --basedir=/usr/local/mysql --initialize-insecure --datadir=/data/3306/data --user=mysql &

6、啟動

mysqld_safe --defaults-file=/etc/my.cnf --user=mysql &

7、登入

mysql -u root

mysql -S /tmp/mysql3306.sock -u root

(4)配置mgr參數

分别在三台配置檔案my.cnf上添加,配置後重新開機生效

101上:transaction_write_set_extraction=XXHASH64

loose-group_replication_group_name ="a876d35e-9110-11e6-a365-842b2b5909d6"

loose-group_replication_start_on_boot =off

loose-group_replication_local_address ="192.168.168.101:34901"

loose-group_replication_group_seeds ="192.168.168.101:34901,192.168.168.102:34902,192.168.168.103:34903"

loose-group_replication_bootstrap_group =off

loose-group-replication-ip-whitelist="192.168.168.101,192.168.168.102,192.168.168.103"

102上:

transaction_write_set_extraction=XXHASH64

loose-group_replication_group_name ="a876d35e-9110-11e6-a365-842b2b5909d6"

loose-group_replication_start_on_boot =off

loose-group_replication_local_address ="192.168.168.102:34902"

loose-group_replication_group_seeds ="192.168.168.101:34901,192.168.168.102:34902,192.168.168.103:34903"

loose-group_replication_bootstrap_group =off

loose-group-replication-ip-whitelist="192.168.168.101,192.168.168.102,192.168.168.103"

103上:

transaction_write_set_extraction=XXHASH64

loose-group_replication_group_name ="a876d35e-9110-11e6-a365-842b2b5909d6"

loose-group_replication_start_on_boot =off

loose-group_replication_local_address ="192.168.168.103:34903"

loose-group_replication_group_seeds ="192.168.168.101:34901,192.168.168.102:34902,192.168.168.103:34903"

loose-group_replication_bootstrap_group =off

loose-group-replication-ip-whitelist="192.168.168.101,192.168.168.102,192.168.168.103"

分别将三台庫重新開機

mysqld\_safe --defaults-file=/etc/my.cnf --user=mysql &

實戰篇:MySQL高可用--MGR實戰

(5)建立組複制使用者

SET SQL\_LOG\_BIN=0;

CREATE USER repl@'%' IDENTIFIED BY 'repl';

GRANT REPLICATION SLAVE ON \*.\* TO repl@'%';

FLUSH PRIVILEGES;

SET SQL\_LOG\_BIN=1;

(6)安裝組複制插件

在3套庫上都安裝

INSTALL PLUGIN group\_replication SONAME 'group\_replication.so';

show plugins;

實戰篇:MySQL高可用--MGR實戰

(7)啟動并引導組複制

在單主模式中我們需要預設的選擇一個節點作為主節點,并且使這個節點成為引導節點。

選擇在101主機上的 mysql 中運作以下的指令

SET GLOBAL group_replication_bootstrap_group=ON;

START GROUP_REPLICATION;

SET GLOBAL group_replication_bootstrap_group=OFF;

SET GLOBAL group\_replication\_bootstrap\_group=ON; 意思是打開節點的引導模式

START GROUP\_REPLICATION; 意思是開啟同步

SET GLOBAL group\_replication\_bootstrap\_group=OFF; 在我們将節點一設定為引導節點後關閉

實戰篇:MySQL高可用--MGR實戰

啟動報錯,檢視日志

實戰篇:MySQL高可用--MGR實戰

set @@global.binlog\_checksum='none';

在3套庫上都需要執行,可以寫入配置檔案

實戰篇:MySQL高可用--MGR實戰

可以檢視到,改節點已經加入到叢集中 ONLINE

實戰篇:MySQL高可用--MGR實戰

在erro日志中看到到節點 1 已經通過 MGR 的内部通信管理 GCS 加入到節點中

實戰篇:MySQL高可用--MGR實戰

檢視是否是主節點,可以看到101主機的庫是主節點

​select * from performance_schema.replication_group_members;查詢節點是否正常​

8.0版本可以直接通過表performance\_schemaerformance\_schema.replication\_group\_members檢視是否是主節點,在5.7中檢視是否主節點需要這樣查

​SELECT IF((SELECT @@server_uuid) = (SELECT VARIABLE_VALUE FROM performance_schema.global_status WHERE VARIABLE_NAME= 'group_replication_primary_member'), 1, 0) as is_primary_node;​

實戰篇:MySQL高可用--MGR實戰

測試:

為了驗證組複制是否能做到加入的節點後自動同步,我們這裡可以在節點 1 上造一點資料

這裡我建立了一些庫和一些表。等節點 2 和節點 3 加入組後觀察是否同步

`​

​create database test; use test; create table t(id int,name varchar(30),PRIMARY KEY (​

​id​

​)); insert into t select 1,'aa';​

​`

實戰篇:MySQL高可用--MGR實戰

(8)節點2加入

set @@global.binlog_checksum='none';CHANGE MASTER TO MASTER_USER='repl', MASTER_PASSWORD='repl' FOR CHANNEL 'group_replication_recovery';

START GROUP_REPLICATION;

2節點加入到叢集,且不是主

實戰篇:MySQL高可用--MGR實戰

如果是8.0的MGR,可以直接從這裡查到是否是主

實戰篇:MySQL高可用--MGR實戰

資料也自動同步過來了,驗證了組複制新加入的節點資料自動同步

實戰篇:MySQL高可用--MGR實戰

(9)節點3加入

set @@global.binlog_checksum='none';CHANGE MASTER TO MASTER_USER='repl', MASTER_PASSWORD='repl' FOR CHANNEL 'group_replication_recovery';

START GROUP_REPLICATION;

3節點加入叢集,且不是主

實戰篇:MySQL高可用--MGR實戰

可以檢視,資料已經同步過來了,再次驗證了組複制新加入的節點資料自動同步

實戰篇:MySQL高可用--MGR實戰

注意:配置檔案沒有寫

`loose-group_replication_single_primary_mode = true

loose-group_replication_enforce_update_everywhere_checks = false`

在5.7中,開始組複制之前,可以手動配置寫入

set global group_replication_single_primary_mode=true;

set global group_replication_enforce_update_everywhere_checks = false;

當然如果不寫,預設是

實戰篇:MySQL高可用--MGR實戰

多主搭建

多主節點搭建基本和單主步驟一樣,隻需要配置檔案my.cnf額外添加,本文以下示例為單主節點搭建,多主節點搭建亦相差無幾

loose-group\_replication\_single\_primary\_mode=FALSE

loose-group\_replication\_enforce\_update\_everywhere\_checks= TRUE

單主搭建(8.0)

1、壓縮包解壓

tar -xvf mysql-8.0.25-linux-glibc2.12-x86_64.tar

rm -rf /usr/local/mysql

mv mysql-8.0.25-linux-glibc2.12-x86_64 /usr/local/mysql

2、配置環境變量

vi /etc/profile

export PATH=/usr/local/mysql/bin:$PATH

source /etc/profile

3、編輯mysql配置檔案

vi /etc/my.cnf

[mysqld]

user=mysql

basedir=/usr/local/mysql

datadir=/data/3306/data

log_bin=/data/3306/binlog/mysql-bin

port=3306

server_id=1013306 #(另外兩台機器 server_id=1023306\ server_id=1033306)

socket=/tmp/mysql.sock

gtid-mode=on

enforce-gtid-consistency=true

log_slave_updates=1

relay_log_info_repository=TABLE

master_info_repository=TABLE

relay_log_recovery=on

--101----------------------------------------------------------------------------------------------------------

transaction_write_set_extraction=XXHASH64

loose-group_replication_group_name ="a876d35e-9110-11e6-a365-842b2b5909d6"

loose-group_replication_start_on_boot =off

loose-group_replication_local_address ="192.168.168.101:34901"

loose-group_replication_group_seeds ="192.168.168.101:34901,192.168.168.102:34902,192.168.168.103:34903"

loose-group_replication_bootstrap_group =off

loose-group-replication-ip-whitelist="192.168.168.101,192.168.168.102,192.168.168.103"

--102----------------------------------------------------------------------------------------------------------

transaction_write_set_extraction=XXHASH64

loose-group_replication_group_name ="a876d35e-9110-11e6-a365-842b2b5909d6"

loose-group_replication_start_on_boot =off

loose-group_replication_local_address ="192.168.168.102:34902"

loose-group_replication_group_seeds ="192.168.168.101:34901,192.168.168.102:34902,192.168.168.103:34903"

loose-group_replication_bootstrap_group =off

loose-group-replication-ip-whitelist="192.168.168.101,192.168.168.102,192.168.168.103"

--103----------------------------------------------------------------------------------------------------------

transaction_write_set_extraction=XXHASH64

loose-group_replication_group_name ="a876d35e-9110-11e6-a365-842b2b5909d6"

loose-group_replication_start_on_boot =off

loose-group_replication_local_address ="192.168.168.103:34903"

loose-group_replication_group_seeds ="192.168.168.101:34901,192.168.168.102:34902,192.168.168.103:34903"

loose-group_replication_bootstrap_group =off

loose-group-replication-ip-whitelist="192.168.168.101,192.168.168.102,192.168.168.103"

------------------------------------------------------------------------------------------------------------

4、建立資料目錄和賦權

mkdir -p /data/3306/data

mkdir -p /data/3306/binlog

chown mysql:mysql -R /data

5、初始化

mysqld --defaults-file=/etc/my.cnf --basedir=/usr/local/mysql --initialize-insecure --datadir=/data/3306/data --user=mysql &

6、啟動

mysqld_safe --defaults-file=/etc/my.cnf --user=mysql &

7、登入

mysql -u root

mysql -S /tmp/mysql3306.sock -u root

8、安裝組複制插件

INSTALL PLUGIN group_replication SONAME 'group_replication.so';

show plugins;9、在101上建立複制使用者SET SQL_LOG_BIN=0;CREATE USER repl@'%' IDENTIFIED WITH mysql_native_password BY 'repl';

GRANT REPLICATION SLAVE ON *.* TO repl@'%';

GRANT BACKUP_ADMIN ON *.* TO repl@'%';

FLUSH PRIVILEGES;

SET SQL_LOG_BIN=1;

10、啟動并引導組複制

在單主模式中我們需要預設的選擇一個節點作為主節點,并且使這個節點成為引導節點。

在 mysql 中運作以下的指令

SET GLOBAL group_replication_bootstrap_group=ON;

START GROUP_REPLICATION;

SET GLOBAL group_replication_bootstrap_group=OFF;11、依次在另外兩個節點CHANGE MASTER TO MASTER_USER='repl', MASTER_PASSWORD='repl' FOR CHANNEL 'group_replication_recovery';

START GROUP_REPLICATION;

如下為8.0的單主三節點MGR叢集

實戰篇:MySQL高可用--MGR實戰

組複制監控常用相關表

MGR單個節點狀态

實戰篇:MySQL高可用--MGR實戰

MGR整個組的狀态

實戰篇:MySQL高可用--MGR實戰

主要用到4張表

performance_schema.replication_group_member_stats

performance_schema.replication_group_members

performance_schema.replication_connection_status

performance_schema.replication_applier_status

1. replication_group_member_stats

是用來展示組複制所有成員資訊的表,有關驗證和應用程式的統計資訊對于了解申請隊列增長情況、觸發了多少沖突、檢查了多少事務、哪些事務已被所有成員送出等等非常有用。

這張表主要是監控各個節點的性能,如果出現某個節點的事務号和其他節點差很多,那這個節點肯定出現了延遲,如果長時間的延遲,極有可能被群員投票給踢出去。

這張表隻有在配置組複制後才會有資料。其中字段包括。

實戰篇:MySQL高可用--MGR實戰

其中最重要的列,也是經常被觀察的指數如下

COUNT_TRANSACTTIONS_IN_QUEUE:組複制隊列中等待沖突檢測的事務數,隻有當沖突檢測通過才會排隊應用到各個節點上(遠端等待被确認的事務數)

COUNT_TRANSACTIONS_REMOTE_IN_APPLIER_QUEUE:目前節點收到的等待的事務數(遠端的事務還有多少沒有被應用)

COUNT_TRANSANCTIONS_CHECKED:已經通過沖突檢測的事務數

COUNT_TRANSACTIONS_REMOTE_APPLIED:目前節點收到的應用的事務數(本地已經應用的事務數)

COUNT_TRANSACTIONS_LOCAL_PROPOSED:源自此成員并發送給複制組的事務數。(本地已經送出的事務數)

----------------------------------------------------------------------------------------------------------------------------

CANNEL_NAME:這個組複制通道的名稱

VIEW_ID:組複制對應的視圖号

MEMBER_ID:複制中組成員的 ID,這個 ID 和本身 mysql 執行個體的 UUID 沒關系

COUNT_CONFLICTS_DETECTED:未通過沖突檢測的事務數

COUNT_TRANSACTIONS_ROWS_VALIDATING:沖突檢查資料庫的大小

TRANSACTIONS_COMMITTED_ALL_MEMBERS:已在複制組的所有成員上成功送出的事務,顯示為 GTID 集。

LAST_CONFLICT_FREE_TRANSACTION:最後一次沖突事務的 GITD 号

COUNT_TRANSACTIONS_REMOTE_APPLIED:目前節點收到的應用的事務數

COUNT_TRANSACTIONS_LOCAL_PROPOSED:源自此成員并發送給複制組的事務數。

COUNT_TRANSACTIONS_LOCAL_ROLLBACK:源自此成員并被複制組復原的事務數。

2.replication_group_members

用于監控組内成員複制狀态的表

實戰篇:MySQL高可用--MGR實戰

CHANNEL_NAME:組複制的通道名

MEMBER_ID:組成員 ID

MEMBER_HOST:組成員的主機名

MEMBER_PORT:組成員資料庫執行個體端口,注意這裡是執行個體端口

MEMBER_STATE:組成員目前的狀态,這個欄位總共有 4 個狀态Online 表示正常工作狀态,表示該節點目前一切 OK。

Recovering 表示節點正在加入組中,這個狀态有可能是正在同步資料,也有可能是正在和主節點發生通信,如果長期處于這個狀态,往往是 host 沒配,需要檢查下 host 配置
Offline 表示這個節點的組複制插件已經加載
Unreachable 表示經過仲裁,某個節點已經崩潰或者不可通路。      

MEMBER_ROLE:成員在組内的角色,如果是單主模式,主的節點就會顯示 PRIMARY,其他節點顯示 SECONDARY,如果是多主模式,所有節點均為 PRIMARY。

MEMBER_VERSION:mysql 的版本

3. replication_connection_status

用于記錄目前節點連接配接狀态的表

實戰篇:MySQL高可用--MGR實戰

CHANNEL_NAME:組複制通道名。

GROUP_NAME:組複制名,就是組的 UUID 号。

SOURCE_UUID:組複制源的 UUID 号。

THREAD_ID:組複制 I/O 功能的 threadid

SERVICE_STATE:顯示成員目前的活躍狀态,

COUNT_RECEIVED_HEARTBEATS:從上一次重置主從後獲得的心跳數

LAST_HEARTBEAT_TIMESTAMP:節點的最後一次心跳時間

RECEIVED_TRANSACTION_SET:與該從站接收的所有事務相對應的一組全局事務 ID(GTID)。如果未使用 GTID,則為空。

LAST_ERROR_NUMBER:最後一次 I/O 同步線程錯誤編号,0 為無錯誤

LAST_ERROR_MESSAGE:最後一次 I/O 同步線程錯誤日志,記錄在 mysql 錯誤日志中

LAST_ERROR_TIMESTAMP:最後一次 I/O 線程錯誤的時間。

LAST_QUEUED_TRANSACTION:該節點同步的 relay log 中最後一個事務的 GTID 号

LAST_QUEUED_TRANSACTION_ORIGINAL_COMMIT_TIMESTAMP:最後一次,在各個節點中寫入的事務準備好送出,産生寫集并且發送到各個節點做沖突校驗時候的時間。

LAST_QUEUED_TRANSACTION_IMMEDIATE_COMMIT_TIMESTAMP:最後一次事務最終送出的時間。LAST_QUEUED_TRANSACTION_START_QUEUE_TIMESTAMP:I / O 線程将最後一個事務放置在 relaylog 中的時間

LAST_QUEUED_TRANSACTION_END_QUEUE_TIMESTAMP:進入 relaylog 排隊的時間

QUEUEING_TRANSACTION:目前 relaylog 中全局事務的 ID

QUEUEING_TRANSACTION_ORIGINAL_COMMIT_TIMESTAMP:目前事務進入寫集的時間

QUEUEING_TRANSACTION_IMMEDIATE_COMMIT_TIMESTAMP:目前事務最後送出的時間

QUEUEING_TRANSACTION_START_QUEUE_TIMESTAMP:目前日志進入 relaylog 的時間

可用此表來判斷延遲

select RECEIVED_TRANSACTION_SET from replication_connection_status where CHANNEL_NAME='group_replication_applier'
union all
select VARIABLE_VALUE from global_variables where VARIABLE_NAME ='gtid_executed';      

本地已經執行的GTID和接收到遠端的GTID的差異

實戰篇:MySQL高可用--MGR實戰

4. replication_applier_status

用于顯示目前組複制線程幹了啥的表

實戰篇:MySQL高可用--MGR實戰

CHANNEL_NAME:複制通道的名字

SERVICE_STATE:當複制通道的應用程式線程處于活動或空閑狀态時顯示為 ON,表示關閉時,應用程式線程未處于活動狀态

REMAINING_DELAY:同步複制線程的延遲時間。

COUNT_TRANSACTIONS_RETRIES:SQL 線程無法應用日志重試的次數

單主多主模式切換

實驗示範規劃

(3台虛拟機。MySQL版本8.0.25)

192.168.168.101 master1(簡稱1節點)

192.168.168.102 slave2   (簡稱2節點)

192.168.168.103 slave3   (簡稱3節點)

在 MGR 中,單主模式是隻有一個主節點可以寫,其餘均為隻讀節點,且隻讀節點的 super read only 為打開狀态,即使 root 使用者依然無法寫。多主模式則為全節點均可寫。

單主切多主

MGR 單切多使用的指令為select group_replication_switch_to_multi_primary_mode();

首先我們觀察目前叢集的模式和各個節點的讀寫模式

select * from performance_schema.replication_group_members;

show variables like '%read_only%';

1節點

實戰篇:MySQL高可用--MGR實戰

2節點

實戰篇:MySQL高可用--MGR實戰

3節點

實戰篇:MySQL高可用--MGR實戰

可以看到,各個節點的讀寫模式是符合單主模式的。接下來我們在任意節點執行切換語句,此處我們在節點 1 上執行。

select group_replication_switch_to_multi_primary_mode();

實戰篇:MySQL高可用--MGR實戰

可以看到節點 1 因為一開始就是主節點,是以讀寫模式沒有發生變化,但是節點 2 和節點 3 已經自動關閉了隻讀模式,所有節點都變成可寫。

實戰篇:MySQL高可用--MGR實戰

多主切單主

MRG 多主切單主有兩條指令可以使用

不指定主節點進行切換

select group_replication_switch_to_single_primary_mode();

MGR 中多主切單主,如果不指定主,切換時遵循以下的規則,前提無延遲情況下,按照優先級先後順序:

1、 先檢查叢集内是否存在低版本的 mysql,如果所有成員都是 8.0.17 版本以上的,則按照更新檔先後順序排列,如果有成員是 8.0.17 版本以下的,或者 5.7 的按發行版本的主要版本來排序,忽略更新檔編号。

2、 如果叢集有任意一個低版本的 mysql。且支援 group_replication_member_weight 這個參數的版本的mysql。則根據 group_replication_member_weight 這個權重參數來,group_replication_member_weight

預設都是 50,權重越高優先級越高。

3、 如果叢集内有不支援 group_replication_member_weight 參數的 mysql,比如有 mysql5.7 的,并且其中一個以上的成員具有最高的成員權重(或忽略了成員權重),則考慮的第三個因素是生成的伺服器 UUID 的詞典順序,由 server_uuid 系統變量指定。伺服器 UUID 最低的成員被選為主伺服器,這裡實際上就是查詢 performance_schema.replication_group_members 最靠前的且是活着的MEMBER_ID。

在節點 1 上執行非指定單主的切換 SQL

實戰篇:MySQL高可用--MGR實戰

可以看到選取了 server_uuid 靠前的節點 1成為主節點。

接下來我們觀察各個節點的讀寫情況

1節點

實戰篇:MySQL高可用--MGR實戰

2節點

實戰篇:MySQL高可用--MGR實戰

3節點

實戰篇:MySQL高可用--MGR實戰

可以看到此時節點 1 作為主節點已經關閉了 read only,其他節點都已經打開了隻讀。

指定單主切換

因為随機切有很大的不确定性,這裡還提供了指定主節點的切換指令

select group_replication_set_as_primary("member_id");

這裡的 member_id 就是 server_uuid我們在節點 1 執行切換指令,選擇2節點的member_id。

切換後,可以看到節點1打開了隻讀變成了從節點

實戰篇:MySQL高可用--MGR實戰

節點2,關閉了隻讀,成為主節點

實戰篇:MySQL高可用--MGR實戰

節點3,不變

實戰篇:MySQL高可用--MGR實戰

異常恢複

網絡異常​​

MGR 對網絡要求很高,有的時候會因網絡波動,自動退出叢集的情況,此時需要先在出問題的節點停止組複制,然後再重新加入到叢集中。

如下,該節點被踢出叢集,直接執行Stop group_replication;報錯

實戰篇:MySQL高可用--MGR實戰

需要先執行 stop group_replication 然後再 start group_replication

Stop group_replication;

Start group_replication;

實戰篇:MySQL高可用--MGR實戰

節點啟動長時間處于RECOVERING

實戰篇:MySQL高可用--MGR實戰

檢視日志

實戰篇:MySQL高可用--MGR實戰

在主節點将密碼的加密方式修改

SET SQL_LOG_BIN=0;

alter USER repl@'%' IDENTIFIED WITH mysql_native_password BY 'repl';

GRANT REPLICATION SLAVE ON *.* TO repl@'%';

GRANT BACKUP_ADMIN ON *.* TO repl@'%';

FLUSH PRIVILEGES;

SET SQL_LOG_BIN=1;

在重新開機兩個從節點

STOP GROUP_REPLICATION;

START GROUP_REPLICATION;

2節點狀态恢複正常

實戰篇:MySQL高可用--MGR實戰

3節點狀态恢複正常

實戰篇:MySQL高可用--MGR實戰

資料異常修複

暫時性恢複

MGR 對資料具有一定的容錯性和最終一緻性,原則上并不會出現資料不一緻的情況,并且每次執行事務都會檢測沖突,然後如果當某個節點的資料因為異常導緻不一緻,切主節點的 binlog 丢失的情況,勢必會導緻叢集資料不一緻,此時可以通過以下的方法暫時讓叢集起來。

停止異常節點的組複制
Stop group_replication;

清空目前的 GTID EXECUTED
Reset master;

在異常節點将 GTID 事務号設定和主節點一緻
SET @@GLOBAL.GTID_PURGED='主節點的 GTID 号';

啟動異常節點的組複制
Start group_replication;      

這裡需要注意,這樣的方式即使恢複了叢集,因為 binlog 的缺失,實際上資料是不一緻的,極有可能發生後續因為資料不一緻導緻叢集出現問題,這裡強烈不建議這麼做。

分布式恢複

前面提到了暫時性的叢集恢複,這樣的恢複會有很大的問題,這裡說下 MGR 正常的恢複方式,MGR 當新的成員加入節點時,通常有兩種方法,當 binlog 全,或者 binlog 在删除前接入的節點能夠成功繼續往下同

步的。則新加入的節點會繼續同步下去,在 mysql8.0.21 版本中,可以通過設定參數

group_replication_advertise_recovery_endpoints 這個參數來進行指定的點進行同步。

如果當 binlog 不可用或者差的資料實在太多時,mysql 在 8.0.17 後退出了克隆的方式進行恢複,即在叢集中的所有 mysql 節點上添加克隆插件,新加入的節點資料将會被全部删除,然後會被自動重新同步資料。

節點分布式恢複

讀節點重新加入環境

模拟讀節點重新加入,首先觀察主節點的資料以及事務的情況

此時将節點 3,然後清除所有資料,清除同步資訊,重新初始化 mysql,模拟成新節點

已有資料

實戰篇:MySQL高可用--MGR實戰

關庫

實戰篇:MySQL高可用--MGR實戰

删資料檔案

實戰篇:MySQL高可用--MGR實戰

此時3節點已經被叢集踢出去了

實戰篇:MySQL高可用--MGR實戰

重新初始化,啟動,并登入

初始化
mysqld --defaults-file=/etc/my.cnf --basedir=/usr/local/mysql --initialize-insecure --datadir=/data/3306/data --user=mysql &

啟動
mysqld_safe --defaults-file=/etc/my.cnf --user=mysql & 

登入
mysql -u root      
實戰篇:MySQL高可用--MGR實戰
實戰篇:MySQL高可用--MGR實戰

這裡注意,因為 2 節點的的 ip 已經添加到了所有節點的 group_replication_group_seeds 中,是以不再添加,如果是新的 ip 加入節點,必須在所有其他節點上 group_replication_group_seeds 中添加新節點的IP。

按照搭建 MGR 節點的步驟,将節點 2 添加到叢集中

Reset master;

INSTALL PLUGIN group_replication SONAME 'group_replication.so';

CHANGE MASTER TO MASTER_USER='repl', MASTER_PASSWORD='repl' FOR CHANNEL 'group_replication_recovery';

START GROUP_REPLICATION;

實戰篇:MySQL高可用--MGR實戰

已經重新加入到叢集中,資料也同步回來

實戰篇:MySQL高可用--MGR實戰
實戰篇:MySQL高可用--MGR實戰

可以看到同步事務已經一緻

實戰篇:MySQL高可用--MGR實戰

克隆恢複

Mysql8.0.17 後可以使用克隆恢複

這裡我們依然采用節點 3 作為需要接收克隆的節點

首先在源節點和接收克隆的節點添加克隆插件

​INSTALL PLUGIN clone SONAME 'mysql_clone.so';​

同樣因為是組複制,是以節點 3 必須裝組複制插件

INSTALL PLUGIN group_replication SONAME 'group_replication.so';

實戰篇:MySQL高可用--MGR實戰

其次在提供克隆的節點上,也就是節點 1 上賦權

​CREATE USER clone_user@'%' IDENTIFIED by '123456'; ​

​GRANT BACKUP_ADMIN ON *.* TO 'clone_user'@'%'; ​

在接收克隆的目标節點,也就是節點 2 上賦權

​CREATE USER clone_user@'%' IDENTIFIED by '123456'; ​

​GRANT CLONE_ADMIN ON *.* TO 'clone_user'@'%'; ​

在接收克隆的目标節點上設定源端的白名單

​SET GLOBAL clone_valid_donor_list = '192.168.168.101:3360'; ​

為了驗證克隆是否會清除接收端上的資料,這裡我們多建幾個 schema在節點3執行

CHANGE MASTER TO MASTER_USER='repl', MASTER_PASSWORD='repl' FOR CHANNEL 'group_replication_recovery';
start GROUP_REPLICATION;      

繼續閱讀