MySQL集羣架構對比
隨着平臺升級,單節點數據庫提供服務已力不從心。現在需要確定一套集羣方案用以部署mysql集羣。考慮到MySQL官方提供的MySQL Cluster(社區版不支持InnoDB引擎),其他第三方方案存在各種各樣的問題,最終選用InnoDB Cluster方案
主要功能
- 部署維護便利
- 遷移簡單
- 定期備份
- 橫向擴展
- 主備、熱切換、易恢復
- 讀寫分離、負載均衡
InnoDB Cluster架構
MySQL InnoDB集羣爲MySQL提供了完整的高可用性解決方案。 MySQL Shell包含AdminAPI,使您可以輕鬆配置和管理一組至少三個MySQL服務器實例,以充當InnoDB集羣。 每個MySQL服務器實例都運行MySQL Group Replication,它提供了在InnoDB集羣內複製數據的機制,具有內置故障轉移功能。Admin API無需在InnoDB集羣中直接使用組複製。 MySQL Shell可以根據您部署的集羣自動配置自身,將客戶端應用程序透明地連接到服務器實例。如果服務器實例意外故障,羣集將自動重新配置。在默認的單主模式下,InnoDB集羣具有單個讀寫服務器實例 - 主要實例。多個輔助服務器實例是主要副本的副本。如果主服務器出現故障,則輔助服務器將自動升級爲主服務器。MySQL路由器檢測到此情況並將客戶端應用程序轉發到新主服務器。高級用戶還可以將羣集配置爲多主結構。
一般採用MySQL Router、Cluster和MySQL Shell構成的Mysql InnoDB Cluster高可用方案進行搭建
結論:
InnoDB Cluster支持自動Failover、強一致性、讀寫分離、讀庫高可用、讀請求負載均衡,橫向擴展的特性,是比較完備的一套方案。但是部署起來複雜,想要解決router單點問題好需要新增組件,如沒有其他更好的方案暫考慮該方案。
基於docker-compose一鍵部署
此案例需創建自定義網絡,創建docker network create sg-net
version: '3'
services:
mysql-server-1:
env_file:
- mysql-server.env
image: mysql/mysql-server:8.0.12
container_name: mysql-server-1
command: ["mysqld","--server_id=1","--innodb_ft_min_token_size=1","--ft_min_word_len=1","--ngram_token_size=1","--binlog_checksum=NONE","--gtid_mode=ON","--enforce_gtid_consistency=ON","--log_bin","--log_slave_updates=ON","--master_info_repository=TABLE","--relay_log_info_repository=TABLE","--transaction_write_set_extraction=XXHASH64","--user=mysql","--skip-host-cache","--skip-name-resolve", "--default_authentication_plugin=mysql_native_password"]
ports:
- "3301:3306"
volumes:
- ./data/mysql-1:/var/lib/mysql
networks:
- sg-net
mysql-server-2:
env_file:
- mysql-server.env
image: mysql/mysql-server:8.0.12
container_name: mysql-server-2
command: ["mysqld","--server_id=2","--innodb_ft_min_token_size=1","--ft_min_word_len=1","--ngram_token_size=1","--binlog_checksum=NONE","--gtid_mode=ON","--enforce_gtid_consistency=ON","--log_bin","--log_slave_updates=ON","--master_info_repository=TABLE","--relay_log_info_repository=TABLE","--transaction_write_set_extraction=XXHASH64","--user=mysql","--skip-host-cache","--skip-name-resolve", "--default_authentication_plugin=mysql_native_password"]
ports:
- "3302:3306"
volumes:
- ./data/mysql-2:/var/lib/mysql
depends_on:
- mysql-server-1
networks:
- sg-net
mysql-server-3:
env_file:
- mysql-server.env
image: mysql/mysql-server:8.0.12
container_name: mysql-server-3
command: ["mysqld","--server_id=3","--innodb_ft_min_token_size=1","--ft_min_word_len=1","--ngram_token_size=1","--binlog_checksum=NONE","--gtid_mode=ON","--enforce_gtid_consistency=ON","--log_bin","--log_slave_updates=ON","--master_info_repository=TABLE","--relay_log_info_repository=TABLE","--transaction_write_set_extraction=XXHASH64","--user=mysql","--skip-host-cache","--skip-name-resolve", "--default_authentication_plugin=mysql_native_password"]
ports:
- "3303:3306"
volumes:
- ./data/mysql-3:/var/lib/mysql
depends_on:
- mysql-server-1
networks:
- sg-net
mysql-shell:
env_file:
- mysql-shell.env
image: neumayer/mysql-shell-batch
container_name: mysql-shell
volumes:
- ./scripts/:/scripts/
depends_on:
- mysql-server-1
- mysql-server-2
- mysql-server-3
networks:
- sg-net
mysql-router:
env_file:
- mysql-router.env
image: mysql/mysql-router:8.0
container_name: mysql-router
restart: on-failure
ports:
- "6446:6446"
depends_on:
- mysql-server-1
- mysql-server-2
- mysql-server-3
- mysql-shell
restart: on-failure
networks:
- sg-net
networks:
sg-net:
external: true
點擊鏈接到github
下載完整代碼與scripts腳本
集羣重啓後無法連接錯誤解決
# 報錯信息
MySQL mysql-server-1:3306 ssl JS > var cluster = dba.getCluster(clusterName)
Dba.getCluster: This function is not available through a session to a standalone instance (metadata exists, but GR is not active) (RuntimeError)
# 第一步:登錄到各節點重置master屬性
mysql>reset master;
# 第二步:重新進入mysql-shell重啓集羣
MySQL mysql-server-1:3306 ssl JS > dba.rebootClusterFromCompleteOutage('devCluster');
Reconfiguring the cluster 'devCluster' from complete outage...
The instance 'mysql-server-2:3306' was part of the cluster configuration.
Would you like to rejoin it to the cluster? [y/N]: y
The instance 'mysql-server-3:3306' was part of the cluster configuration.
Would you like to rejoin it to the cluster? [y/N]: y
The cluster was successfully rebooted.
<Cluster:devCluster>
# 第三步:連接集羣並查看狀態
MySQL mysql-server-1:3306 ssl JS > var cluster = dba.getCluster(clusterName)
MySQL mysql-server-1:3306 ssl JS > cluster.status()
{
"clusterName": "devCluster",
"defaultReplicaSet": {
"name": "default",
"primary": "mysql-server-1:3306",
"ssl": "DISABLED",
"status": "OK",
"statusText": "Cluster is ONLINE and can tolerate up to ONE failure.",
"topology": {
"mysql-server-1:3306": {
"address": "mysql-server-1:3306",
"mode": "R/W",
"readReplicas": {},
"role": "HA",
"status": "ONLINE"
},
"mysql-server-2:3306": {
"address": "mysql-server-2:3306",
"mode": "R/O",
"readReplicas": {},
"role": "HA",
"status": "ONLINE"
},
"mysql-server-3:3306": {
"address": "mysql-server-3:3306",
"mode": "R/O",
"readReplicas": {},
"role": "HA",
"status": "ONLINE"
}
}
},
"groupInformationSourceMember": "mysql://root@mysql-server-1:3306"
}
# 可以看到status都是ONLINE,說明重啓成功
重啓mysql-routerdocker restart mysql-router
常用操作命令
# 檢查節點配置實例,用於加入cluster之前
dba.checkInstanceConfiguration("root@hostname:3306")
# 重啓
dba.rebootClusterFromCompleteOutage('myCluster');
# 刪除schema
dba.dropMetadataSchema();
# 獲取當前集羣
var cluster = dba.getCluster('myCluster')
# 檢查cluster裏節點狀態
cluster.checkInstanceState("root@hostname:3306")
# 重新加入節點,我本地測試的時候發現rejoin一直無效,每次是delete後
cluster.rejoinInstance("root@hostname:3306")
# 刪除集羣
addcluster.dissolve({force:true})
# 增加節點
cluster.addInstance("root@hostname:3306")
# 刪除節點
cluster.removeInstance("root@hostname:3306")
# 強制刪除節點
cluster.removeInstance('root@host:3306',{force:true})
# 解散集羣
cluster.dissolve({force:true})
# 集羣描述
cluster.describe();
# update the metadata
cluster.rescan();