前言
在企業級應用中,資料庫的高可用性(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 由以下三個核心元件組成:
- MySQL Group Replication:提供資料複製與自動故障轉移功能
- MySQL Shell:管理與設定叢集的進階命令列工具
- 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 1 | mysql-node1 | 192.168.1.101 | 初始 Primary |
| Node 2 | mysql-node2 | 192.168.1.102 | Secondary |
| Node 3 | mysql-node3 | 192.168.1.103 | Secondary |
| Router | mysql-router | 192.168.1.100 | 應用連線入口 |
設定主機名稱解析
在所有節點的 /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
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 延遲
安全性建議
- 使用 SSL/TLS 加密叢集通訊
- 限制管理帳號來源 IP
- 定期更換密碼
- 啟用審計日誌
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,可實現自動化的故障轉移和負載平衡。本文詳細說明了從環境準備到叢集建立的完整流程,以及監控管理的最佳實踐。建議在正式部署前,充分測試故障轉移場景,確保叢集能夠滿足業務的可用性需求。