MySQL 高可用:InnoDB Cluster 部署詳解

最近公眾號有人留言:為啥使用 ProxySQL 而不使用 InnoDB Cluster ?
其實使用什么方案,根據(jù)實際情況進行權衡利弊即可,如果先部署了 MGR ,想在此基礎之上完善高可用,添加 ProxySQL 比較方便。如果新部署一個高可用環(huán)境,直接使用 InnoDB Cluster 也可以,InnoDB Cluster 也是依賴 MGR 。
下面從零開始,來講解怎么通過 Docker Compose 來部署 MySQL InnoDB Cluster,讓你能夠快速搭建一套完整的高可用數(shù)據(jù)庫系統(tǒng)。
什么是 MySQL InnoDB Cluster
核心概念
MySQL InnoDB Cluster是 MySQL 官方提供的高可用解決方案,它基于以下三個核心組件:
- MySQL Group Replication:提供數(shù)據(jù)復制和故障檢測,這個就是前面文章中提到的 MGR
- MySQL Router:提供透明的路由和負載均衡
- MySQL Shell:提供集群管理和監(jiān)控功能
架構優(yōu)勢
- 自動故障檢測和轉(zhuǎn)移
- 強一致性數(shù)據(jù)復制
- 透明的讀寫分離
- 簡化的管理操作
架構圖開始部署
為了測試方便,在一臺服務器上使用 docker compose 部署多個服務節(jié)點。
啟動 MySQL 節(jié)點
在服務器上創(chuàng)建一個目錄 mysql-innodb-cluster ,目錄中按照下圖進行目錄和文件的創(chuàng)建。
docker-compose.yml 文件內(nèi)容如下:
version: '3.8'
services:
mysql1:
image: mysql:8.0.39
container_name: mysql1
hostname: mysql1
restart: unless-stopped
environment:
MYSQL_ROOT_PASSWORD: rootpass123
TZ: Asia/Shanghai
networks:
- mysql-cluster-net
volumes:
- ./node1/conf:/etc/mysql/conf.d:ro
- ./node1/data:/var/lib/mysql
- ./node1/log:/var/log/mysql
ports:
- "3310:3306"
mysql2:
image: mysql:8.0.39
container_name: mysql2
hostname: mysql2
restart: unless-stopped
environment:
MYSQL_ROOT_PASSWORD: rootpass123
TZ: Asia/Shanghai
networks:
- mysql-cluster-net
volumes:
- ./node2/conf:/etc/mysql/conf.d:ro
- ./node2/data:/var/lib/mysql
- ./node2/log:/var/log/mysql
ports:
- "3311:3306"
mysql3:
image: mysql:8.0.39
container_name: mysql3
hostname: mysql3
restart: unless-stopped
environment:
MYSQL_ROOT_PASSWORD: rootpass123
TZ: Asia/Shanghai
networks:
- mysql-cluster-net
volumes:
- ./node3/conf:/etc/mysql/conf.d:ro
- ./node3/data:/var/lib/mysql
- ./node3/log:/var/log/mysql
ports:
- "3312:3306"
mysql-router:
image: mysql/mysql-router:8.0
container_name: mysql-router
restart: unless-stopped
depends_on:
- mysql1
- mysql2
- mysql3
networks:
- mysql-cluster-net
volumes:
- ./router/data:/tmp/mysqlrouter
ports:
- "6446:6446" # 讀寫端口 (RW)
- "6447:6447" # 只讀端口 (RO)
- "6448:6448" # 管理端口 (X Protocol RW)
- "6449:6449" # 管理端口 (X Protocol RO)
environment:
MYSQL_HOST: mysql1
MYSQL_PORT: 3306
MYSQL_USER: clusteradmin
MYSQL_PASSWORD: clusterpass123
MYSQL_CREATE_ROUTER_USER: 0
MYSQL_ROUTER_BOOTSTRAP_EXTRA_OPTIONS: >
--conf-use-sockets
--conf-bind-address 0.0.0.0
--conf-base-port 6446
networks:
mysql-cluster-net:
driver: bridge
name: mysql-cluster-netrouter 節(jié)點說明:
- 檢測
/tmp/mysqlrouter/mysqlrouter.conf是否存在,如果不存在則執(zhí)行mysqlrouter --bootstrap clusteradmin@mysql1:3306 ... --directory /tmp/mysqlrouter,密碼從MYSQL_PASSWORD變量讀入,非交互(不用手動輸入)。 - bootstrap 成功后,以后每次容器重啟直接
mysqlrouter -c /tmp/mysqlrouter/mysqlrouter.conf不再重新掃描集群,配置持久化。 - Router 根據(jù)集群實時角色,把 6446 流量轉(zhuǎn)發(fā)到 PRIMARY,6447 轉(zhuǎn)發(fā)到 SECONDARY,應用只需連固定端口即可。
mysql 節(jié)點 1 的配置文件 mysql1.cnf 內(nèi)容如下:
[mysqld]
# 網(wǎng)絡和連接
bind-address = 0.0.0.0
# 復制基礎
server_id = 1
log_bin = mysql-bin
binlog_format = ROW
enforce_gtid_consistency = ON
gtid_mode = ON
# Group Replication 特定配置
transaction_write_set_extraction = XXHASH64
loose-group_replication_group_name = "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa" # 請?zhí)鎿Q為一個有效的UUID,可使用 `uuidgen` 命令生成
loose-group_replication_start_on_boot = OFF
loose-group_replication_local_address = "mysql1:33061" # 內(nèi)部組通信地址和端口,通常為 33061
loose-group_replication_group_seeds = "mysql1:33061, mysql2:33061, mysql3:33061"
loose-group_replication_single_primary_mode = ON # 單主模式
loose-group_replication_bootstrap_group = OFF # 切勿隨意開啟引導
# Innodb Cluster 元數(shù)據(jù)存儲
disabled_storage_engines = MyISAM,BLACKHOLE,FEDERATED,ARCHIVE
# 性能與可靠性
binlog_transaction_dependency_tracking = WRITESETmysql 節(jié)點 2 的配置文件 mysql2.cnf 內(nèi)容如下:
[mysqld]
bind-address = 0.0.0.0
server_id = 2
log_bin = mysql-bin
binlog_format = ROW
enforce_gtid_consistency = ON
gtid_mode = ON
transaction_write_set_extraction = XXHASH64
loose-group_replication_group_name = "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa" # 必須與node1相同
loose-group_replication_start_on_boot = OFF
loose-group_replication_local_address = "mysql2:33061"
loose-group_replication_group_seeds = "mysql1:33061, mysql2:33061, mysql3:33061"
loose-group_replication_single_primary_mode = ON
loose-group_replication_bootstrap_group = OFF
disabled_storage_engines = MyISAM,BLACKHOLE,FEDERATED,ARCHIVE
binlog_transaction_dependency_tracking = WRITESETmysql 節(jié)點 3 的配置文件 mysql3.cnf 內(nèi)容如下:
[mysqld]
bind-address = 0.0.0.0
server_id = 3
log_bin = mysql-bin
binlog_format = ROW
enforce_gtid_consistency = ON
gtid_mode = ON
transaction_write_set_extraction = XXHASH64
loose-group_replication_group_name = "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa" # 必須與node1相同
loose-group_replication_start_on_boot = OFF
loose-group_replication_local_address = "mysql3:33061"
loose-group_replication_group_seeds = "mysql1:33061, mysql2:33061, mysql3:33061"
loose-group_replication_single_primary_mode = ON
loose-group_replication_bootstrap_group = OFF
disabled_storage_engines = MyISAM,BLACKHOLE,FEDERATED,ARCHIVE
binlog_transaction_dependency_tracking = WRITESET節(jié)點 3 內(nèi)容與節(jié)點 2 類似,但 server_id 必須改為 3,loose-group_replication_local_address 改為 mysql3:33061。loose-group_replication_group_name 必須與其它節(jié)點相同。
關于配置文件中 mgr 相關的部分可以參考之前的文章《MySQL高可用-使用Docker部署MGR》。
執(zhí)行下面的命令,先啟動三個 mysql 節(jié)點。
docker-compose up -d mysql1 mysql2 mysql3等三個 mysql 節(jié)點都啟動成功后,再執(zhí)行下面的操作。
添加集群管理賬戶
在三個 MySQL 節(jié)點上,都需要創(chuàng)建一個用于集群管理和 Router 引導的管理員用戶(需要 SYSTEM_VARIABLES_ADMIN, REPLICATION_SLAVE_ADMIN, GROUP_REPLICATION_ADMIN 權限)。
先使用下面命令連接到節(jié)點 1 的 shell:
# 連接到 mysql1 容器并登錄 MySQL
docker-compose exec mysql1 mysql -uroot -prootpass123然后執(zhí)行下面的語句進行 clusteradmin 賬戶的創(chuàng)建和權限設置:
CREATE USER IF NOT EXISTS 'clusteradmin'@'%' IDENTIFIED WITH mysql_native_password BY 'clusterpass123';
GRANT ALL PRIVILEGES ON *.* TO 'clusteradmin'@'%' WITH GRANT OPTION;
FLUSH PRIVILEGES;在節(jié)點 2 和節(jié)點 3 上執(zhí)行相同的操作。
使用 mysql shell 構建集群
配置和啟動 InnoDB Cluster,可以使用 MySQL Shell (mysqlsh) 來創(chuàng)建集群。臨時啟動一個 MySQL Shell 容器。
docker run --rm -it --network=mysql-cluster-net mysql/mysql-server:8.0 mysqlsh執(zhí)行成后會進入到 MySQL JS 的 shell 界面,如下圖:
在 shell 模式下逐步執(zhí)行下面的代碼:
// 連接到第一個節(jié)點(將成為初始主節(jié)點)
\connect clusteradmin@mysql1:3306
// 提供密碼:clusterpass123
// 檢查實例配置是否符合集群要求
dba.checkInstanceConfiguration('clusteradmin@mysql1:3306');
dba.checkInstanceConfiguration('clusteradmin@mysql2:3306');
dba.checkInstanceConfiguration('clusteradmin@mysql3:3306');
// 創(chuàng)建集群,命名為 'myCluster'
var cluster = dba.createCluster('myCluster');
// 添加其他實例到集群中
cluster.addInstance('clusteradmin@mysql2:3306', {password: 'your_strong_clusteradmin_password', recoveryMethod: 'clone'}); // 使用 clone 方式進行恢復
cluster.addInstance('clusteradmin@mysql3:3306', {password: 'your_strong_clusteradmin_password', recoveryMethod: 'clone'});
// 檢查集群狀態(tài)
cluster.status();節(jié)點成功添加到集群中如下圖:
最后查看集群狀態(tài):
輸出應顯示三個實例都是 ONLINE,其中一個角色是 PRIMARY,另外兩個是 SECONDARY。
啟動并配置 MySQL Router
執(zhí)行下面命令啟動 router 容器
docker-compose up -d mysql-routerrouter 啟動成功的日志如下:
到這 MySQL InnoDB Cluster 已經(jīng)部署完成,可以使用 Navicat 之類的工具進行連接進行測試:
使用 Navicat 時需要注意,SSL 中的使用 SSL 必須勾選。
最后
一開始想使用 AI 來生成所有的配置,嘗試了很多次,沒有能一次性成功的,根據(jù)日志中的錯誤信息讓 AI 修改,越改越混亂。因為整個過程中我沒有參與,給不出更多有價值的信息,最后放棄了讓 AI 直接來操作。
從這個過程我體會到更好使用 AI 的方式應該是:
- 先讓 AI 總結(jié)出部署 MySQL InnoDB Cluster 的關鍵步驟。
- 從這個步驟中了解到一些基本的原理,然后分步驟讓 AI 搞定配置,實操的過程中也是分步驟進行,這樣即便出現(xiàn)問題也比較容易排查。
- 手動一步一步去操作,有助于更好的理解和理清邏輯關系。
- 學習任何技術,我們自己懂的越多,就越能讓 AI 發(fā)揮更大的能力。




























