随着平台升级,单节点数据库提供服务已力不从心。现在需要确定一套集群方案用以部署mysql集群。考虑到MySQL官方提供的MySQL Cluster(社区版不支持InnoDB引擎),其他第三方方案存在各种各样的问题,最终选用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 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-js> shell.connect('root@mysql-server-1:3306');
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>
# 第三步:连接集群并查看状态,可以看到status都是ONLINE,说明重启成功
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"
}
重启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();
要想了解InnoDB Cluster主从工作原理,请参考跨主机MySQL主从复制