Ubuntu 22.04 MySQL 高可用叢集架構

Ubuntu 22.04 MySQL High Availability Cluster Architecture

前言

在企業級應用中,資料庫的高可用性(High Availability, HA)是確保業務連續性的關鍵要素。MySQL InnoDB Cluster 提供了一個完整的高可用解決方案,整合了 MySQL Group Replication、MySQL Shell 和 MySQL Router,可實現自動故障轉移和負載平衡。本文將詳細說明如何在 Ubuntu 22.04 環境下建立 MySQL 高可用叢集。

MySQL 高可用概述

MySQL 高可用叢集的核心目標是確保資料庫服務的持續運作,即使在單一節點發生故障時也能自動切換至健康節點,最大程度減少服務中斷時間。

高可用性的關鍵指標

可用性等級年停機時間適用場景
99%3.65 天開發環境
99.9%8.76 小時一般業務系統
99.99%52.56 分鐘關鍵業務系統
99.999%5.26 分鐘金融/電商核心系統

架構選項比較

常見 MySQL 高可用方案

方案優點缺點適用場景
主從複製設定簡單、資源消耗低需手動故障轉移讀寫分離、備份
MHA (Master HA)成熟穩定、自動故障轉移需額外管理節點中型企業
Galera Cluster多主架構、強一致性寫入效能受限需多點寫入場景
InnoDB Cluster官方支援、整合度高至少需要三節點企業級應用

本文將聚焦於 MySQL InnoDB Cluster,這是 Oracle 官方推薦的高可用解決方案。

MySQL InnoDB Cluster 概念

InnoDB Cluster 由以下三個核心元件組成:

  1. MySQL Group Replication:提供資料複製與自動故障轉移功能
  2. MySQL Shell:管理與設定叢集的進階命令列工具
  3. MySQL Router:應用程式連線的中介層,提供透明的故障轉移

叢集拓撲結構

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
                    ┌─────────────────┐
                    │  MySQL Router   │
                    │   (負載平衡)     │
                    └────────┬────────┘
         ┌───────────────────┼───────────────────┐
         │                   │                   │
         ▼                   ▼                   ▼
┌─────────────┐     ┌─────────────┐     ┌─────────────┐
│   Primary   │     │  Secondary  │     │  Secondary  │
│  (讀/寫)    │◄───►│   (唯讀)    │◄───►│   (唯讀)    │
│  Node 1     │     │   Node 2    │     │   Node 3    │
└─────────────┘     └─────────────┘     └─────────────┘

環境準備

伺服器規劃

角色主機名稱IP 位址說明
Node 1mysql-node1192.168.1.101初始 Primary
Node 2mysql-node2192.168.1.102Secondary
Node 3mysql-node3192.168.1.103Secondary
Routermysql-router192.168.1.100應用連線入口

設定主機名稱解析

在所有節點的 /etc/hosts 中新增:

1
sudo vim /etc/hosts
1
2
3
4
192.168.1.101 mysql-node1
192.168.1.102 mysql-node2
192.168.1.103 mysql-node3
192.168.1.100 mysql-router

MySQL Shell 安裝

MySQL Shell 是管理 InnoDB Cluster 的核心工具,需在所有節點安裝。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
# 下載 MySQL APT Repository
wget https://dev.mysql.com/get/mysql-apt-config_0.8.29-1_all.deb

# 安裝 MySQL APT 設定
sudo dpkg -i mysql-apt-config_0.8.29-1_all.deb

# 更新套件清單
sudo apt update

# 安裝 MySQL Server 和 MySQL Shell
sudo apt install mysql-server mysql-shell -y

# 確認安裝版本
mysqlsh --version

設定 MySQL 節點

在每個節點編輯 MySQL 設定檔 /etc/mysql/mysql.conf.d/mysqld.cnf

1
sudo vim /etc/mysql/mysql.conf.d/mysqld.cnf
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
[mysqld]
# 節點識別碼(每個節點必須唯一)
server_id = 1  # Node 2 設為 2,Node 3 設為 3

# 啟用 GTID(Group Replication 必要)
gtid_mode = ON
enforce_gtid_consistency = ON

# 二進位日誌設定
log_bin = mysql-bin
binlog_format = ROW
binlog_checksum = NONE

# 允許遠端連線
bind-address = 0.0.0.0

# Group Replication 設定
plugin_load_add = 'group_replication.so'
group_replication_group_name = "aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee"
group_replication_start_on_boot = OFF
group_replication_local_address = "192.168.1.101:33061"
group_replication_group_seeds = "192.168.1.101:33061,192.168.1.102:33061,192.168.1.103:33061"
group_replication_bootstrap_group = OFF

# 效能調校
innodb_buffer_pool_size = 1G
innodb_log_file_size = 256M

重啟 MySQL 服務:

1
sudo systemctl restart mysql

建立 InnoDB Cluster

建立叢集管理帳號

在所有節點執行以下操作:

1
sudo mysql -u root
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
-- 建立叢集管理帳號
CREATE USER 'clusteradmin'@'%' IDENTIFIED BY 'YourClusterPassword123!';

-- 授予必要權限
GRANT ALL PRIVILEGES ON *.* TO 'clusteradmin'@'%' WITH GRANT OPTION;
GRANT CLONE_ADMIN, CONNECTION_ADMIN, GROUP_REPLICATION_ADMIN,
      PERSIST_RO_VARIABLES_ADMIN, REPLICATION_APPLIER,
      REPLICATION_SLAVE_ADMIN, ROLE_ADMIN, SYSTEM_VARIABLES_ADMIN
      ON *.* TO 'clusteradmin'@'%';

FLUSH PRIVILEGES;

使用 MySQL Shell 設定節點

連線至第一個節點:

1
mysqlsh clusteradmin@mysql-node1
1
2
3
4
5
// 檢查節點是否符合 InnoDB Cluster 需求
dba.checkInstanceConfiguration('clusteradmin@mysql-node1:3306')

// 設定節點(如需要)
dba.configureInstance('clusteradmin@mysql-node1:3306')

建立叢集

在 MySQL Shell 中執行:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
// 建立叢集
var cluster = dba.createCluster('MyCluster')

// 查看叢集狀態
cluster.status()

// 新增第二個節點
cluster.addInstance('clusteradmin@mysql-node2:3306')

// 新增第三個節點
cluster.addInstance('clusteradmin@mysql-node3:3306')

// 確認叢集狀態
cluster.status()

驗證叢集狀態

1
2
// 詳細狀態資訊
cluster.status({extended: 1})

輸出範例:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
{
    "clusterName": "MyCluster",
    "defaultReplicaSet": {
        "name": "default",
        "primary": "mysql-node1:3306",
        "status": "OK",
        "topology": {
            "mysql-node1:3306": {
                "mode": "R/W",
                "status": "ONLINE"
            },
            "mysql-node2:3306": {
                "mode": "R/O",
                "status": "ONLINE"
            },
            "mysql-node3:3306": {
                "mode": "R/O",
                "status": "ONLINE"
            }
        }
    }
}

MySQL Router 設定

MySQL Router 作為應用程式與叢集之間的中介層,提供自動故障轉移與負載平衡。

安裝 MySQL Router

1
sudo apt install mysql-router -y

設定 Router Bootstrap

使用 bootstrap 模式自動設定 Router:

1
2
3
4
sudo mysqlrouter --bootstrap clusteradmin@mysql-node1:3306 \
  --directory /etc/mysqlrouter \
  --user=mysqlrouter \
  --conf-use-sockets

啟動 MySQL Router

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
# 建立 systemd 服務
sudo cp /etc/mysqlrouter/mysqlrouter.service /etc/systemd/system/

# 啟動服務
sudo systemctl daemon-reload
sudo systemctl start mysqlrouter
sudo systemctl enable mysqlrouter

# 確認狀態
sudo systemctl status mysqlrouter

Router 設定檔說明

設定檔位於 /etc/mysqlrouter/mysqlrouter.conf

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
[routing:MyCluster_rw]
bind_address = 0.0.0.0
bind_port = 6446
destinations = metadata-cache://MyCluster/?role=PRIMARY
routing_strategy = first-available
protocol = classic

[routing:MyCluster_ro]
bind_address = 0.0.0.0
bind_port = 6447
destinations = metadata-cache://MyCluster/?role=SECONDARY
routing_strategy = round-robin-with-fallback
protocol = classic
  • 埠 6446:連線至 Primary 節點(讀寫)
  • 埠 6447:連線至 Secondary 節點(唯讀,負載平衡)

故障轉移測試

模擬 Primary 節點故障

在 Primary 節點執行:

1
2
# 停止 MySQL 服務
sudo systemctl stop mysql

觀察故障轉移

在另一節點使用 MySQL Shell 查看:

1
2
var cluster = dba.getCluster()
cluster.status()

系統將自動選舉新的 Primary 節點。

恢復節點

1
2
# 重新啟動 MySQL
sudo systemctl start mysql

在 MySQL Shell 中重新加入叢集:

1
cluster.rejoinInstance('clusteradmin@mysql-node1:3306')

監控與管理

叢集健康檢查

1
2
3
4
5
6
7
8
// 檢查叢集狀態
cluster.status({extended: 2})

// 檢查路由資訊
cluster.listRouters()

// 檢查執行個體設定
cluster.checkInstanceState('clusteradmin@mysql-node2:3306')

常用管理指令

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
// 設定選項
cluster.setOption('exitStateAction', 'ABORT_SERVER')
cluster.setOption('memberWeight', 50)

// 移除節點
cluster.removeInstance('clusteradmin@mysql-node3:3306')

// 強制重新設定叢集(僅在多數節點失效時使用)
cluster.forceQuorumUsingPartitionOf('clusteradmin@mysql-node1:3306')

// 解散叢集
cluster.dissolve()

效能監控指標

1
2
3
4
5
6
7
8
9
-- 查看 Group Replication 成員狀態
SELECT * FROM performance_schema.replication_group_members;

-- 查看複製延遲
SELECT * FROM performance_schema.replication_group_member_stats\G

-- 查看交易認證佇列
SELECT COUNT_TRANSACTIONS_IN_QUEUE
FROM performance_schema.replication_group_member_stats;

最佳實踐

網路設定

  • 使用專用網路進行叢集通訊
  • 確保節點間網路延遲低於 10ms
  • 開放必要埠:3306(MySQL)、33061(Group Replication)
1
2
3
4
5
# 防火牆設定
sudo ufw allow 3306/tcp
sudo ufw allow 33061/tcp
sudo ufw allow 6446/tcp
sudo ufw allow 6447/tcp

效能優化

  • 根據記憶體調整 innodb_buffer_pool_size(建議 50-70% 記憶體)
  • 啟用 group_replication_flow_control_mode 控制流量
  • 使用 SSD 儲存以降低 I/O 延遲

安全性建議

  1. 使用 SSL/TLS 加密叢集通訊
  2. 限制管理帳號來源 IP
  3. 定期更換密碼
  4. 啟用審計日誌
1
2
3
-- 啟用 SSL 複製
SET GLOBAL group_replication_ssl_mode = 'REQUIRED';
SET GLOBAL group_replication_recovery_use_ssl = ON;

備份策略

1
2
3
4
5
6
# 使用 MySQL Shell 備份
mysqlsh clusteradmin@mysql-node1 -- util dumpInstance /backup/full_backup

# 或使用 mysqldump
mysqldump --all-databases --single-transaction --routines --triggers \
  -u clusteradmin -p > /backup/full_backup.sql

參考資料

結語

MySQL InnoDB Cluster 提供了企業級的高可用解決方案,透過整合 Group Replication、MySQL Shell 和 MySQL Router,可實現自動化的故障轉移和負載平衡。本文詳細說明了從環境準備到叢集建立的完整流程,以及監控管理的最佳實踐。建議在正式部署前,充分測試故障轉移場景,確保叢集能夠滿足業務的可用性需求。

comments powered by Disqus
Built with Hugo
Theme Stack designed by Jimmy