MySQL8.0 高可用叢集化 · mysql-shell · mysql-router · docker · 單主多從

2023-02-15 15:00:46

高可用叢集的基本特點

負載均衡 / 讀寫分離 / 故障轉移
本文以此為目標,利用 mysql-shell、mysql-router,基於 docker 的環境架構(篇幅太長,內容多了點兒)。

一、名詞及要點

名詞 解釋
GR Group Replication;叢集間的主從節點資料複製,利用 gtid、binlog 等確保所有節點資料的一致。
DDL Data Definition Language;操作庫本身的語句。如 CREATE/ALTER/DROP等語句;自動提交當前事務;不能回滾。
DML Data Manipulation Language;針對資料的操作,如 CRUD,可回滾。

本文主要闡述內容:

    • 叢集化設定項的作用說明
    • mysql-shell 組建管理叢集
    • mysql-router 叢集路由
    • 叢集總體測試驗證

二、環境說明

2.1 環境詳細

名稱 標籤 角色
Rockylinux 9.1 本次整體測試虛擬機器器;可參考:https://rockylinux.org
mysql-shell 8.0.31 用來管理叢集
mysql-router 8.0.31 叢集路由服務
docker 20.10.22 叢集服務容器載體
docker image:oraclelinux 9-slim 用來部署 mysql-router 的映象
docker image:mysql 8.0.31 叢集範例服務映象
mysql-cli 8.0.31 用來測試驗證連線的使用者端

2.2 環境架構

    • Linux VM 中安裝 mysql-shell
    • Linux VM 中安裝 docker(執行3個mysql容器、一個mysql-router容器)
    • Linux VM 中安裝 mysql-client

環境架構圖範例

應用安裝層次圖

MySQL叢集 - 應用安裝層次圖

三、環境準備

- docker 的安裝在這裡省略。
- 網路地址全部使用 hostname 代替 IP 相互通訊。
- 所有 MySQL 系相關的應用版本計劃統一為 8.0.31。
- 所有 MySQL 涉及到的賬號,為了測試便捷,以下都用 root / 統一密碼操作。

3.1 docker 拉取所需的映象

mysql image:利用官方提供的映象,後續執行容器作為叢集的節點

oraclelinux image:官方提供的系統映象,後續為執行 mysql-router 的容器

# 拉取oraclelinux系統映象
docker pull oraclelinux:9-slim
# 拉取MySQL官網提供的映象
docker pull mysql:8.0.31

3.2 docker 建立叢集專用網段

叢集,當然建議固定 ip,甚至設定叢集 hosts;這對於叢集內部網路高並行下是很有必要的網路優化。

為此,這裡單獨建立一個虛擬網路,後續應用到叢集中。(計劃本次測試不涉及跨主機的網路轉發)

# 這裡建立一個名稱為 br-mysql-clus 的自定義網路,計劃叢集所有節點處在同一網段下
docker network create --subnet=12.12.0.0/24 --gateway=12.12.0.254 br-mysql-clus

3.3 叢集 hosts 設定

計劃叢集中的每個節點都用固定 IP,並指明 hostname,以 hostname 相互通訊(這在叢集中提升了通訊的效率)

計劃所有的容器 hosts 檔案都繫結到 Linux VM/etc/hosts;所以主機 hosts 設定所有節點的 IP > hostname:

127.0.0.1   localhost localhost.localdomain localhost4 localhost4.localdomain4
::1         localhost localhost.localdomain localhost6 localhost6.localdomain6
fe00::0 ip6-localnet
ff00::0 ip6-mcastprefix
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters

# 追加叢集各節點的 IP > hostname
# 以下定義,為後續容器的執行做準備
12.12.0.1       mc1    # mysql cluster node 1
12.12.0.2       mc2    # mysql cluster node 2
12.12.0.3       mc3    # mysql cluster node 3
12.12.0.5       mr     # mysql router

四、基於叢集的 MySQL8 設定項說明

4.1 必須設定項

如果不設定以下各項,後續組建叢集的 shell 會逐一列出不符合叢集要求的項,並提醒完成必須的設定。

server_id:叢集各節點唯一標識,必須為數位型;基於此設定會自動生成設定項 server_uuid 的值。

gtid_mode / dnforce_gtid_consistency:開啟組複製 / 並保持事務的一致性,這個很重要。

group_replication_single_primary_mode:本次計劃的 單主多從 叢集模式。

binlog_transaction_dependency_tracking:叢集同步資料時更精確的事務處理方式。

group_replication_group_name:統一的名稱才可識別為屬於同一個叢集。

[mysqld]
# 各節點的唯一識別,各節點cnf唯一不同之處,只能是數位
server_id = 1
# 開啟組複製的叢集資料同步功能
gtid_mode = ON
enforce_gtid_consistency = ON
# 指明單主多從模式
loose-group_replication_single_primary_mode = ON
loose-binlog_transaction_dependency_tracking = WRITESET
# 叢集名稱,必為有效的UUID
loose-group_replication_group_name = "a53e2dec-a5fe-11ed-99b8-080027c5c3a3"

什麼是 GTID

全域性事務識別符號;GTID 是建立的唯一識別符號,基於事務的資料複製,可以識別和跟蹤源伺服器上提交的每個事務,在源和拓撲伺服器上均唯一;它在源伺服器上提交併由任何副本應用,源和副本之間始終保留GTID,只要在源上提交的所有事務也在副本上提交,在源上提交的事務只能在副本上應用一次,就可以保證兩者之間的一致性。

4.2 需要關注的設定項

設定項說明解釋:

group_replication_start_on_boot:節點加入叢集時,自動開始複製 Master 資料功能,以保持節點間資料一致。

group_replication_bootstrap_group:叢集啟動後是否作為 Master 節點,自動開始RG;建議都設為 OFF。

group_replication_local_address:叢集內各節點之間,當前節點對外的通訊地址。

group_replication_group_seeds:叢集啟動時,組建的基本節點。

[mysqld]
# 啟動後自動執行組複製,預設=ON
#loose-group_replication_start_on_boot = ON

# 重啟後的叢集以哪個範例的資料為準的複製同步過程
#loose-group_replication_bootstrap_group = OFF

# 明確本節點的對外通訊地址(不是必須,shell指令碼可覆蓋代替)
# 當 communication_stack = MYSQL 時,以下埠只能3306
# 當 communication_stack = XCOM 時,以下埠建議33061
#loose-group_replication_local_address="{host}:3306"

# 種子節點,由每個節點的通訊地址組成(不是必須,shell指令碼可覆蓋代替)
#loose-group_replication_group_seeds="{host}:3306,{host}:3306,{host}:3306"

需要注意的設定項 group_replication_bootstrap_group

假設1:所有節點都設為 OFF,重啟的叢集不會自動開始組複製(GR)功能
假設2:多節點設為 ON,系統分不清以哪個節點為基準的組複製(GR)功能(腦裂現象)
假設3:固定一個節點設為 ON,此節點的資料在叢集中不一定是最完整的

所以,重啟後的叢集,人為的選擇 Master,手動啟動組複製(GR)最為妥當

方案1:叢集啟動前,選好一臺 ON 作為 Master,叢集啟動後,需改為 OFF
方案2:在被人為認定的 Master 主機上,手動啟動GR,如下指令碼:
  mysql> SET GLOBAL group_replication_bootstrap_group = ON;
  mysql> START GROUP_REPLICATION USER='***', PASSWORD='***';
  mysql> SET GLOBAL group_replication_bootstrap_group = OFF;

4.3 需要知道的設定項

以下預設值都已符合叢集執行的基本要求,或者不同場景,您需要不同的設定。

log_bin:二進位制紀錄檔,包括所有(DDL/DML)指令碼的執行記錄,用於實時主從資料同步/資料恢復。

log_replica_updates:同步過來的二進位制更新紀錄檔,也需要記錄到自己的二進位制紀錄檔中;便於災難時的恢復。

binlog_format:資料同步紀錄檔記錄的程度;一般的/更細的/混合的;當然ROW更細的紀錄檔會帶來更龐大的空間佔用。

[mysqld]
#log_bin = ON                        # default = ON
#log_replica_updates = ON            # default = ON
#binlog_format = ROW                 # default = ROW
#master_info_repository = TABLE      # default = TABLE
#relay_log_info_repository = TABLE   # default = TABLE

什麼是 binlog

Binary Log;以二進位制的形式記錄了對於資料庫的變更過程。
binlog可設定單檔案大小,過期時間等;多用於:資料恢復、主從同步。

binlog 的三種記錄方式:
STATEMENT:能夠記錄大多數的指令碼變更過程;
ROW:記錄所有的指令碼變更細節,空間佔用過大;
MIXED:不同方式壓縮記錄所有指令碼的變更,確保資料的一致性、準確性。

4.4 可適當調整的擴充套件設定項

[mysqld]
# 持久化設定,預設=NO
# 引數或設定儲存起來,如:組建時產生的賬戶密碼,重啟後依然有效
#persisted_globals_load = ON

# 選舉權重百分比,預設=50,正序排列優先順序
#loose-group_replication_member_weight = 50

# 新版 預設=MYSQL,舊版預設=XCOM
# 各節點通訊埠不可隨意使用:MYSQL必須用3306,XCOM可以用33061
# group_replication_communication_stack = MYSQL

# 事務寫入演演算法方式(組複製預設的XXHASH64,<=8.0.1版本預設值為OFF)
#transaction_write_set_extraction = XXHASH64

# 設定群組白名單,包含在內的節點才能加入
#(舊版本CommunicationStack=XCOM時有效)
#loose-group_replication_ip_whitelist="192.168.1.0/24"

# 複製單位大小;預設 150000000 位元組,可適當加大以提升複製效率
#loose-group_replication_transaction_size_limit = 1500000000

# 資料複製時,外來鍵級聯檢測;本次測試不需要那麼嚴謹,預設=OFF
#loose-group_replication_enforce_update_everywhere_checks = OFF

# 為建立 InnoDB Cluster,所要遮蔽的庫表型別,預設值如下
#disabled_storage_engines = "MyISAM,BLACKHOLE,FEDERATED,ARCHIVE,MEMORY"

以上 cnf 中絕大多數的設定項,在後續 shell 管理叢集時,都會有對應的引數設定,以覆蓋 cnf 原有設定

五、mysql-shell 組建 MySQL 叢集

5.1 準備各節點組態檔

這裡以[4.1 必須設定項]為模板,分別建立三個 cnf 組態檔:mc1.cnfmc2.cnfmc3.cnf

後續容器啟動時,分別對應各自節點的 cnf 檔案。各 cnf 唯一不同的設定項是server_id

5.2 docker 啟動多個SQL範例容器

這裡假設三個SQL範例(叢集至少),用 docker container 啟動執行起來。

執行容器為叢集必要的繫結項

    • 指定計算機名
    • 指定固定 IP
    • 指定同一 hosts 檔案(為確保 hostname 的識別)
    • 指定各節點的 cnf 組態檔

以下唯一不同的是:hostname、ip、container-name、cnf 項。

# 第一個SQL容器的啟動
docker run -dit \
    --restart unless-stopped \        # 非人為宕機後自動重啟
    -e LANG=C.utf8 \                  # 設定系統字元集
    -e TZ=Asia/Shanghai \             # 設定系統時區
    -e MYSQL_ROOT_PASSWORD=sa. \      # SQL範例 root 密碼
    --network br.mysql.clus \         # 使用的網路名稱(自定義建立的網路)
    --ip 12.12.0.1 \                  # 指定 IP,叢集模式建議固定 IP
    --name mysql.clus.n1 \            # 容器名稱
    --hostname mc1 \                  # 容器內計算機名稱(用以叢集內的節點通訊)
    -v /etc/hosts:/etc/hosts \        # 統一 hosts 設定
    -v /my/mc1.cnf:/etc/my.cnf \      # 各範例的組態檔
    mysql:8.0.31
# 第二個SQL容器的啟動
docker run -dit \
    --restart unless-stopped \
    -e LANG=C.utf8 -e TZ=Asia/Shanghai \
    -e MYSQL_ROOT_PASSWORD=sa. \
    --network br.mysql.clus --ip 12.12.0.2 \
    --name mysql.clus.n2 --hostname mc2 \
    -v /etc/hosts:/etc/hosts \
    -v /my/mc2.cnf:/etc/my.cnf \
    mysql:8.0.31
# 第三個SQL容器的啟動
docker run -dit \
    --restart unless-stopped \
    -e LANG=C.utf8 -e TZ=Asia/Shanghai \
    -e MYSQL_ROOT_PASSWORD=sa. \
    --network br.mysql.clus --ip 12.12.0.3 \
    --name mysql.clus.n3 --hostname mc3 \
    -v /etc/hosts:/etc/hosts \
    -v /my/mc3.cnf:/etc/my.cnf \
    mysql:8.0.31

記住以上三個容器的SQL映象提供的環境變數 MYSQL_ROOT_PASSWORD,也就是給 SQL Instance 的 root 設定密碼為 sa.;在後續的過程當中,都以 root 及這樣的密碼作為憑證。

叢集三個節點容器執行效果,這裡把各自節點容器名稱分別為:
mysql.clus.n1
mysql.clus.n2
mysql.clus.n3

5.3 mysql-shell 介紹

作為叢集節點的管理工具,安裝在任意(Win/Linux)網路互通的系統都可以,這裡用官網提供的 [MySQL Yum Repository] 的方式安裝到 Linux VM

可參考官網:https://dev.mysql.com/doc/mysql-yum-repo-quick-guide/en/

# MySQL Yum Repository 安裝到 Linux 系統中
dnf install https://repo.mysql.com/mysql80-community-release-el9-1.noarch.rpm -y
dnf clean all && dnf makecache
# 在 Repository 中搜尋以 mysql-shell 為字首的應用
dnf list mysql-shell*
# 安裝特定版本的 mysql-shell
dnf install -y mysql-shell-8.0.31

這裡已經安裝過,截圖僅是搜尋並安裝的範例:

安裝完成後,進入 mysql-shell 命令列請輸入:mysqlsh

mysql-shell 提供了三種命令模式:JavaScript / python / sql;預設為 js 模式。

這裡說明一下接下來常用到的 mysqlsh 命令:

全域性物件 說明
dba 用於叢集的管理
mysql SQL服務連線物件
shell 通用函數
os 與系統有關的操作
util 工具函數
shell 通用命令 說明
\? ; \help 獲得幫助
\js ; \py ; \sql 切換模式
\ 多行命令
\c ; \connect {user}:{host}:{port} 連線到目標範例
\disconnect 斷開連線對談
\reconnect 重新連線到對談
\! ; \system 執行系統指令碼
\q ; \quit ; \exit 退出當前對談(mysql-shell)

在接下來的過程當中,經常會用

\js 方式組建管理 MySQL 叢集
\sql 方式查詢目標範例的資料資訊

5.4 MySQL AdminAPI

在 mysqlsh 中,使用 MySQL AdminAPI 提供的dba物件及函數來 檢測節點/建立叢集/設定叢集/解散叢集/重啟叢集 等的叢集管理操作。

有關於 AdminAPI 的研究,可參考官方檔案:https://dev.mysql.com/doc/mysql-shell/8.0/en/admin-api-userguide.html

接下來以dba物件為主的叢集管理操作。

5.5 檢測節點範例

前期,已經執行了三個MySQL容器,參考[5.2 docker 啟動多個SQL範例容器],並且設定了執行叢集的必要引數;但在建立叢集前,通常都會檢驗目標範例是否符合加入叢集的要求:

先連線任意一個 Instance,比如:\c root@mc1:3306(還記得 root 密碼麼,也許會讓你輸入憑證)

然後檢測所有節點的設定,是否符合叢集的基本執行條件(各 cnf 的必須設定項,未配好的會提醒)

# 分別檢測各節點(還記得先前設定的 hosts 各名稱麼)
dba.checkInstanceConfiguration('root@mc1:3306');
dba.checkInstanceConfiguration('root@mc2:3306');
dba.checkInstanceConfiguration('root@mc3:3306');

過程如下截圖範例:

如果檢測失敗

1、可用 \c 方式連線到目標範例後
2、再用 dba.configureLocalInstance(); 方法引導完成必須的設定

5.6 建立叢集

# 在任意目標範例中,建立名為 clus-1 的叢集
# 那麼,當前範例會被作為 Master 角色存在
var clus = dba.createCluster('clus-1');
# 或者,也可以指定目標範例名稱,建立叢集
# 如:dba.createCluster('clus-1',{localAddress:'root@mc2:3306'});
# 還記得名為 group_replication_local_address 的設定引數麼,所以以上 localAddress 的值會覆蓋此引數值
#
# 叢集建立完成後,可用 status(); 函數檢視當前叢集狀態資訊
clus.status();
#
# 也可以獲取當前節點所處的叢集
var clus1 = dba.getCluster();

mysql-shell 創建叢集 並檢視叢集狀態

從上圖可以看出:此節點為叢集的主節點、可讀可寫、單主多從模式、叢集內部通訊地址為 mc1:3306。

5.7 加入新節點

加入節點,需要設定資料恢復(與主節點保持一致)的方式:克隆、增量、自動。

可以加引數指明方式;也可以在新增過程中按系統提示選擇。

# 加入新的叢集節點,過程中通常選擇 Clone 模式來複制主節點的資料
clus.addInstance('root@mc2:3306');
clus.addInstance('root@mc3:3306');
# 當然也有提醒資訊;
# 比如:clus.addInstance('root@mc2:3306',{localAddress:'root@mc2:3306'});
# 追加的 localAddress 引數,更明確的指出此節點對叢集的通訊地址
# 所以也可省略的引數,mysqlsh 也可自動取範例 Uri 作為 localAddress 引數值
#
# 此時再 .status() 檢視叢集狀態
clus.status();

叢集新增新節點圖例:

叢集 .status() 狀態資訊圖例:

... ... 加入更多的節點;單主多從的叢集建立完成。

節點自動連線到叢集

當因為連線超時或效能壓力等,被自動踢出叢集的節點,恢復後自動連線到叢集;
或人為修復故障後,可以手動通過 rejoinInstance() 函數再次連線到叢集中;
被 removeInstance() 的節點恢復正常後,通過 addInstance() 再次加入叢集。

5.8 常用叢集管理函數

全域性函數 說明
dba.configureLocalInstance(); 設定當前節點為符合叢集的要求,不符合的設定項會自動提示。
dba.checkInstanceState({Uri}); 檢查節點設定,列出節點的當前具體情況(衝突/分歧/錯誤)。
dba.configureInstance({Uri}, { option:value }); 設定遠端SQL範例節點引數。
dba.checkInstanceConfiguration({Uri}); 檢查指定節點是否符合加入叢集的要求。
dba.createCluster({cluster-name}); 以指定(預設:當前)節點上下文為基準,建立一個叢集。
dba.getCluster({cluster-name}); 取得當前節點所處/引數指定的叢集物件。
dba.rebootClusterFromCompleteOutage({cluster-name}); 重啟指定的叢集(建議先 check 各節點)
dba.dropMetadataSchema(); 刪除整個 Schema(無法恢復)。
當前叢集物件函數 說明
{cluster}.addInstance({Uri}); 叢集加入新節點。
{cluster}.status(); 叢集狀態資訊。
{cluster}.describe(); 叢集結構資訊。
{cluster}.removeInstance({Uri}); 叢集內移除指定的節點範例。
{cluster}.rescan(); (屬於叢集)列出未執行在叢集內的節點範例。
{cluster}.rejoinInstance({Uri}); (故障節點修復後)重新連線到叢集。
{cluster}.foreQuorumUsingPartitionOf({Uri}); 恢復叢集(建議先 check 各節點)
{cluster}.dissolve(); 解散叢集(各節點資料保持現狀)。
{cluster}.help({fun-name}); 幫助;所有函數 或 指定函數。
{cluster}.options(); 列出此叢集可配引數。
{cluster}.setOption({option}, {value}); 為此叢集設定設定項。
{cluster}.setInstanceOption({Uri}, { option:value }); 為此叢集的指定節點範例,設定設定項。
{cluster}.listRouters(); 檢視路由資訊
{cluster}.setupAdminAccount({account-name}); 為叢集中的所有節點統一建立相同的賬戶高許可權及密碼(替代root)。
{cluster}.setupRouterAccount({account-name}); 為叢集中的路由統一建立相同的賬戶高許可權及密碼(替代root)。

函數應用場景案例:重啟叢集

可能預先要做的準備工作:在叢集中尋找資料集更接近完善的節點,以作為 Master 節點。

    • 生成叢集節點報告,從中做出最佳選擇:dba.rebootClusterFromCompleteOutage({ dryRun : true });
    • 依次連線到每個SQL範例,並執行指令碼後對比GTID事務量:show variables like '%gtid_executed%';

引數應用場景案例:節點異常時踢出叢集前的延遲時長

當某個節點異常時,系統會有5秒的檢測時長,之後還會有延遲時長,後踢出叢集;為了防止被誤踢,延遲時長可配。

    • 比如在首次加入叢集時設定引數:{cluster}.addInstance({Uri},{ expelTimeout : 8 });
    • 再比如非首次的後續設定方式:{cluster}.setInstanceOption({Uri},{expelTimeout:8});

那,,,mysql-shell 管理的叢集有哪些引數可以設定的呢?

{cluster}.options();函數列出每個節點的所有可設定引數:(擷取部分)

有沒有熟悉的引數。。。

這裡 options 所有的引數都與 cnf 組態檔引數一一對應;

比如:可以用dba.createCluster('{Uri}',{ key:value, key:value ... });這樣的方式附帶引數

比如:可以用.addInstance('{Uri}',{ key:value, key:value ... });這樣的方式附帶引數

也可以用函數.setOption( option, value );這樣的方式完成引數設定。

用 mysql-shell 管理叢集時,預設情況下,以上都可覆蓋原有(my.cnf)設定,並可持久化(my-auto.cnf)儲存。

六、叢集 GR 測試

6.1 GR 資料同步測試

測試場景:在 Master 節點建立庫/表/資料後;檢視 Slave 節點是否已同步資料。

# 在 Master 節點建立庫/表/資料
\c root@mc1:3306
create database clusterdb;
create table clusterdb.emp(id bigint not null AUTO_INCREMENT,usercode VARCHAR(32) DEFAULT NULL,createtime datetime default now(),PRIMARY KEY (id));
insert into clusterdb.emp(usercode) values ('Sol'),('wang');
# 檢視 Slave 節點是否已同步資料
\c root@mc2:3306
select * from clusterdb.emp;

測試結果圖:主從資料同步完成

6.2 故障轉移測試

測試場景:Master 節點製造宕機(停機),叢集選舉出新的 Master 節點,是否完成故障轉移

1、假設的 Master 宕機:docker stop mysql.clus.n1
2、再檢視叢集 Master 角色所處節點。

# 連線到叢集節點
mysqlsh --uri root@mc2:3306
# 檢視叢集節點狀況
dba.getCluster().status();

測試結果上圖:其中 mc2:3306 節點已接替 Master 角色,完成故障轉移

七、建立 mysql-router 容器加入叢集

docker mysql-router 映象,官網有測試版,參考:https://hub.docker.com/r/mysql/mysql-router

既然非生產環境的穩定版,這裡在容器中安裝 mysql-router。

7.1 容器中部署 mysql-router

執行已有的 oraclelinux 映象,並進入容器:

# oraclelinux 映象執行出新容器
docker run -dit --restart unless-stopped -e LANG=C.utf8 -e TZ=Asia/Shanghai \
    --name mysql.clus.mr --hostname mr \
    --network br.mysql.clus --ip 12.12.0.5 \
    -p 6446:6446 -p 6447:6447 \
    -v /etc/hosts:/etc/hosts \
    oraclelinux:9-slim
# 進入容器
docker exec -it mysql.clus.mr bash

容器內安裝 mysql-router

通常:docker 映象的系統,只提供最基本的應用功能,最大程度的簡化,是 docker image 的特點之一。
所以:以下映象的容器內,yum/dnf 已被移除,rpm 也被簡化,但僅提供了最簡陋的應用安裝方式 microdnf。
當然:也可以通過 microdnf 來安裝上功能強大的 yum/dnf 等,以下繼續使用 microdnf 方式安裝應用。

# 這裡使用官方提供的 Yum Repository 方式安裝
curl -#O https://repo.mysql.com/mysql80-community-release-el9-1.noarch.rpm
rpm -ivh mysql80-community-release-el9-1.noarch.rpm
# 作為映象的微型系統,當然是僅提供基本功能
# yum/dnf 都沒了,當然也可以安裝上,這裡使用自帶的 microdnf 命令安裝
# 更新 Repos,為了後續更快的應用安裝(多等會)
microdnf clean all && microdnf makecache
# 模糊搜尋以 mysql-router 為字首的安裝包
microdnf repoquery mysql-router*
# 搜尋到的包,安裝指定版本;格式:{name}-{版本號}
microdnf install mysql-router-community-8.0.31 -y
# 檢視安裝效果
mysqlrouter -V

7.2 容器內啟動 mysql-router

# 命令有多種可選引數,這裡用以下方式初始化 mysql-router 範例
# 叢集 Master主機的URI格式:{sql-user}:{pass}@{host}:{port}
mysqlrouter --bootstrap root:sa.@mc1:3306 --user=root --force
# 初始化後產生的組態檔可檢視,或修改設定項
cat /etc/mysqlrouter/mysqlrouter.conf
# 啟動後臺執行範例
mysqlrouter --user=root &

7.3 或製作成 mysql-router 映象

a、建立空資料夾,作為製作映象的根目錄;

b、資料夾中建立 Dockerfile 檔案:touch Dockerfile

  Dockerfile 檔案內容如下:

# 基於 Oracle 9 Linux 系統的依賴
FROM oraclelinux:9-slim
# 系統預設字元集
ENV LANG C.utf8
# 系統預設時區
ENV TZ Asia/Shanghai
# mysql-router 用到的叢集 Master Uri 作為系統變數
# 叢集 Master Uri 格式為:{user}:{pass}@{host}:{port}
ENV MASTER_URI root:sa.@mc1:3306
# 以下執行在指定賬戶下
USER root
# 進入系統後的預設目錄
WORKDIR ~
# 製作系統所需的命令步驟
# - 網路安裝MySQL官網提供的 Yum Repository,編譯 mysql-router 在此 Repo 下安裝
RUN rpm -ivh https://repo.mysql.com/mysql80-community-release-el9-1.noarch.rpm
RUN microdnf clean all
RUN microdnf makecache
RUN microdnf install mysql-router-community-8.0.31 -y
RUN mysqlrouter --bootstrap $MASTER_URI -u=root --force
# 對外提供 mysql-router 的讀寫埠
EXPOSE 6446 6447
# mysql-router 初始化 並 啟動
ENTRYPOINT mysqlrouter -u=root

c、Dockerfile 檔案儲存退出後,在此目錄下執行 build 命令,生成 image 包。

# build 格式:docker build -t {image-name}:{tag} {根目錄}
docker build -t mysql/router8:1.0 .
# 檢視 image list
docker image ls

將製作的 mysql/router8 映象執行到容器

docker run -dit \
    --restart unless-stopped \            # 非手動關機時自動重啟
    --name mysql.clus.mr \                # 容器名稱
    --hostname mr \                       # 計算機名
    --network br.mysql.clus \             # 指定網路
    --ip 12.12.0.5 \                      # 叢集時建議使用固定IP
    -p 6446:6446 -p 6447:6447 \           # 對外開發的埠對映
    -v /my/mr.hosts:/etc/hosts \          # 叢集時的 hosts 優化
    -e MASTER_URI=root:sa.@mc2:3306 \     # 叢集 Master uri 地址
    mysql/router8:1.0                     # 使用製作的映象

範例節點 + 路由 的容器列表:

叢集檢視路由資訊:listRouters()

所以,,,使用者端在連線的時候,不同的動作連線對應的埠號。

八、叢集路由測試

首先,使用者端 mysql-cli 先連線到 mysql-router;

mysql-router 按叢集狀況,把讀寫動作連線到不同的叢集節點上。

8.1 基於路由的 - 讀寫分離

8.1.1 寫入埠 6446 測試

測試辦法:使用者端 mysql-cli 連線 mysql-router 的寫入埠 6446,是否連線到 Master?

# mysql-cli 連線到 mysql-router
mysql -h mr -u root -P 6446 -p
# - 驗證連線的主機(是不是 mc1)
select @@hostname, @@port;

上圖測試結果顯示:路由的 6446 埠連線到 Master,並可寫入資料;測試通過

8.1.2 唯讀埠 6447 測試

測試辦法:使用者端 mysql-cli 連線 mysql-router 的唯讀埠 6447,是否連線到 Slave?

# mysql-cli 連線到 mysql-router
mysql -h mr -u router_newuser_1 -P 6447 -p
# - 驗證連線的主機(是不是 mc2,mc3)
select @@hostname, @@port;
# - 驗證資料是否已經同步到從機
select * from emp;

上圖測試結果顯示:路由的 6447 埠,連線到了 Slave 節點,並可查詢資料;測試通過

8.3 基於路由的 - 負載均衡

測試場景:透過路由 6447 唯讀埠,多次連線查詢資料,是否輪詢連線到不同的唯讀節點?

上圖測試結果顯示:多次連線唯讀埠,連線到了不同的唯讀節點;測試通過