Docker搭建InnoDB Cluster集群

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(); 
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章