news 2026/2/17 15:09:03

MySQL8.0高可用集群架构实战

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
MySQL8.0高可用集群架构实战

MySQL InnoDB Cluster

一、基本概述

InnoDB Cluster是MySQL官方实现高可用+读写分离的架构方案,其中包含以下组件
  • MySQL Group Replication,简称MGR,是MySQL的主从同步高可用方案,包括数据同步及角色选举
  • Mysql Shell是InnoDB Cluster的管理工具,用来创建和管理集群
  • Mysql Router是业务流量入口,支持对MGR的主从角色判断,可以配置不同的端口分别对外提供读写服务,实现读写分离
MySQL Router与组复制和MySQL Shell高度整合,只有将其与组复制和MySQL Shell共同使用,才能够称为InnoDB Cluster。

二、集群架构

InnoDB Cluster将三个MySQL数据库实例构成一个高可用集群。其中一个实例是具有读/写能力的主要成员,其他两个实例是具有只读能力的次要成员。组复制将数据从主要成员复制到次要成员。MySQL Router将客户端应用程序连接到集群的主要成员。

三、搭建一主两从InnoDB集群

1. 安装3个数据库实例

可以利用docker快速部署3个MySQL实例

主机名(角色)

server_id

宿主机IP

容器固定IP

DB Port

mgr-node1(primary)

1

192.168.65.223

172.19.0.10

3321>3306

mgr-node2(Secondary)

2

192.168.65.223

172.19.0.11

3322>3306

mgr-node3(Secondary)

3

192.168.65.223

172.19.0.12

3323>3306

# 创建组复制的网络 保证三个mysql容器之间可以通过容器名访问 docker network create --driver bridge --subnet 172.19.0.0/24 --gateway 172.19.0.1 mgr-network mkdir -p /mysql/mgr/node1/data /mysql/mgr/node1/conf /mysql/mgr/node1/log mkdir -p /mysql/mgr/node2/data /mysql/mgr/node2/conf /mysql/mgr/node2/log mkdir -p /mysql/mgr/node3/data /mysql/mgr/node3/conf /mysql/mgr/node3/log #以mgr-node1配置为例,创建/mysql/mgr/node1/conf/custom.cnf,添加以下配置: vim /mysql/mgr/node1/conf/custom.cnf [mysql] # 设置mysql客户端默认编码 default-character-set=utf8 [mysqld] #指定sever_id,三个Mysql实例需要分别改为对应的sever_id server_id=1 # 必须开启GTID支持 gtid_mode=ON enforce_gtid_consistency=ON # 启用二进制日志 log-bin=mysql-bin #启用并行复制 binlog_transaction_dependency_tracking=WRITESET replica_preserve_commit_order=ON replica_parallel_type=LOGICAL_CLOCK transaction_write_set_extraction=XXHASH64 #对于Group Replication,数据必须存储在InnoDB事务存储引擎中 disabled_storage_engines="MyISAM,BLACKHOLE,FEDERATED,ARCHIVE,MEMORY" # mgr-node2和mgr-node3同上,注意配置文件路径和修改server_id vim /mysql/mgr/node2/conf/custom.cnf [mysql] # 设置mysql客户端默认编码 default-character-set=utf8 [mysqld] #指定sever_id,三个Mysql实例需要分别改为对应的sever_id server_id=2 # 必须开启GTID支持 gtid_mode=ON enforce_gtid_consistency=ON # 启用二进制日志 log-bin=mysql-bin #启用并行复制 binlog_transaction_dependency_tracking=WRITESET replica_preserve_commit_order=ON replica_parallel_type=LOGICAL_CLOCK transaction_write_set_extraction=XXHASH64 #对于Group Replication,数据必须存储在InnoDB事务存储引擎中 disabled_storage_engines="MyISAM,BLACKHOLE,FEDERATED,ARCHIVE,MEMORY" vim /mysql/mgr/node3/conf/custom.cnf [mysql] # 设置mysql客户端默认编码 default-character-set=utf8 [mysqld] #指定sever_id,三个Mysql实例需要分别改为对应的sever_id server_id=3 # 必须开启GTID支持 gtid_mode=ON enforce_gtid_consistency=ON # 启用二进制日志 log-bin=mysql-bin #启用并行复制 binlog_transaction_dependency_tracking=WRITESET replica_preserve_commit_order=ON replica_parallel_type=LOGICAL_CLOCK transaction_write_set_extraction=XXHASH64 #对于Group Replication,数据必须存储在InnoDB事务存储引擎中 disabled_storage_engines="MyISAM,BLACKHOLE,FEDERATED,ARCHIVE,MEMORY" #运行mysql容器 # 为了便于测试,启动容器时指定好IP、hostname docker run -d \ --name mgr-node1 \ --privileged=true \ --restart=always \ --ip 172.19.0.10 \ --hostname mgr-node1 \ --add-host mgr-node2:172.19.0.11 \ --add-host mgr-node3:172.19.0.12 \ --network mgr-network \ -p 3321:3306 \ -v /mysql/mgr/node1/data:/var/lib/mysql \ -v /mysql/mgr/node1/conf:/etc/mysql/conf.d \ -v /mysql/mgr/node1/log:/logs \ -e MYSQL_ROOT_PASSWORD=123456 \ -e TZ=Asia/Shanghai mysql:8.0.27 \ --lower_case_table_names=1 docker run -d \ --name mgr-node2 \ --privileged=true \ --restart=always \ --ip 172.19.0.11 \ --hostname mgr-node2 \ --add-host mgr-node1:172.19.0.10 \ --add-host mgr-node3:172.19.0.12 \ --network mgr-network \ -p 3322:3306 \ -v /mysql/mgr/node2/data:/var/lib/mysql \ -v /mysql/mgr/node2/conf:/etc/mysql/conf.d \ -v /mysql/mgr/node2/log:/logs \ -e MYSQL_ROOT_PASSWORD=123456 \ -e TZ=Asia/Shanghai mysql:8.0.27 \ --lower_case_table_names=1 docker run -d \ --name mgr-node3 \ --privileged=true \ --restart=always \ --ip 172.19.0.12 \ --hostname mgr-node3 \ --add-host mgr-node1:172.19.0.10 \ --add-host mgr-node2:172.19.0.11 \ --network mgr-network \ -p 3323:3306 \ -v /mysql/mgr/node3/data:/var/lib/mysql \ -v /mysql/mgr/node3/conf:/etc/mysql/conf.d \ -v /mysql/mgr/node3/log:/logs \ -e MYSQL_ROOT_PASSWORD=123456 \ -e TZ=Asia/Shanghai mysql:8.0.27 \ --lower_case_table_names=1 # 在宿主机上配置mysql容器的ip和host映射 vim /etc/hosts 172.19.0.10 mgr-node1 172.19.0.11 mgr-node2 172.19.0.12 mgr-node3

所有实例分别配置远程访问

# 以node1为例 docker exec -it mgr-node1 /bin/bash mysql -u root -p123456 #进入mysql执行 ALTER USER 'root'@'%' IDENTIFIED WITH mysql_native_password BY '123456'; flush privileges;

2. 安装mysqlrouter和安装mysqlshell

MySQL Router是MySQL Proxy的后继产品,它提供了MySQL协议的路由器功能,可以用来实现读写分离、负载均衡和高可用性解决方案。

安装mysql-router

下载地址:https://downloads.mysql.com/archives/router/https://downloads.mysql.com/archives/router/

# 以centos7为例 wget https://downloads.mysql.com/archives/get/p/41/file/mysql-router-community-8.0.27-1.el7.x86_64.rpm rpm -ivh mysql-router-community-8.0.27-1.el7.x86_64.rpm
安装mysql-shell

下载地址:https://downloads.mysql.com/archives/shell/https://downloads.mysql.com/archives/shell/

# 以centos7为例 wget https://downloads.mysql.com/archives/get/p/43/file/mysql-shell-8.0.27-1.el7.x86_64.rpm rpm -ivh mysql-shell-8.0.27-1.el7.x86_64.rpm
# 远程连接mysql mysqlsh root@192.168.65.223:3321 --js mysqlsh root@mgr-node1:3306 --js

MySQL Shell 教程:https://share.note.youdao.com/s/IpZEoHG0https://share.note.youdao.com/s/IpZEoHG0

MySQL Shell的操作依赖两个核心端口,防火墙必须开放这些端口才能保证集群正常通信:

端口

用途

说明

3306

MySQL服务端口

MySQL Shell连接MySQL服务器的默认端口(如mgr-node1:3306)。

33061

Group Replication通信端口

集群节点之间同步数据/状态的默认端口(如

mgr-node1:33061)。

当防火墙阻塞上述端口时,会出现以下错误(对应你之前的操作场景):
  • 连接MySQL服务器失败ERROR: MySQL server at 'mgr-node2:3306' can't connect to 'mgr-node1:3306'(3306端口被阻塞)。
  • Group Replication通信失败ERROR: RuntimeError: Server address configuration error(33061端口被阻塞)。
  • 节点无法加入集群: 即使MySQL服务启动,节点仍显示OFFLINE(端口未开放导致无法同步)。

3. InnoDB Cluster 初始化

3.1 参数及权限配置预需求检测

在添加实例到集群中前,使用该方法检查实例配置是否满足InnoDB 集群要求。

mysqlsh root@192.168.65.223:3321 --js // 检查实例是否符合InnoDB Cluster的参数及权限配置要求 dba.checkInstanceConfiguration('root@mgr-node1:3306') dba.checkInstanceConfiguration('root@mgr-node2:3306') dba.checkInstanceConfiguration('root@mgr-node3:3306')
如果验证通过返回ok。
如果验证没通过,比如出现下面的日志提示,需要mysql实例开启gtid和指定server_id
搭建InnoDB Cluster需要满足的要求如下:
InnoDB集群使用了Group Replication,因此必须满足使用组复制的要求。具体可以参考https://dev.mysql.com/doc/refman/8.0/en/group-replication-requirements.htmlhttps://dev.mysql.com/doc/refman/8.0/en/group-replication-requirements.html其中比较重要的几点有:
  • 必须开启二进制日志,并且日志格式为ROW,即--log-bin和binlog_format=row(默认);
  • 必须开启副本更新日志,即log_replica_updates=ON(默认) ;
  • 必须开启GTID,即gtid_mode=ON和enforce_gtid_consistency=ON。
  • 存储引擎只能使用InnoDB。最好禁用其他存储引擎:
disabled_storage_engines="MyISAM,BLACKHOLE,FEDERATED,ARCHIVE,MEMORY"
  • 从8.0.23开始,集群中的实例要启用并行复制。需要配置以下系统变量:
binlog_transaction_dependency_tracking=WRITESET slave_preserve_commit_order=ON slave_parallel_type=LOGICAL_CLOCK transaction_write_set_extraction=XXHASH64
3.2 初始化InnoDB Cluster相关配置
// 对实例配置InnoDB Cluster相关参数 dba.configureInstance('root@mgr-node1:3306') dba.configureInstance('root@mgr-node2:3306') dba.configureInstance('root@mgr-node3:3306')

4.创建一主两从InnoDB集群

集群常用命令
#会列出dba相关指令 dba.help(); #列出详细指令的用法 dba.help('deploySandboxInstance'); #检查节点配置实例,用于加入cluster之前 dba.checkInstanceConfiguration("root@hostname:3306"); #节点初始化 dba.configureInstance('root@hostname:3306'); #重启集群 dba.rebootClusterFromCompleteOutage('myCluster'); #会列出集群相关指令 cluster.help(); #创建集群 var cluster = dba.createCluster('myCluster'); #获取当前集群实例 var cluster = dba.getCluster('myCluster'); 查看集群状态 cluster.status(); #检查cluster节点状态 cluster.checkInstanceState("root@hostname:3306") ; #增加节点 cluster.addInstance("root@hostname:3306") ; #删除节点 cluster.removeInstance("root@hostname:3306") ; #强制删除节点 cluster.removeInstance('root@hostname:3306',{force:true}); # 状态为missing的节点可以重新加入集群 cluster.rejoinInstance("root@hostname:3306") #解散集群 cluster.dissolve({force:true}) ; #集群描述 cluster.describe();
进入主节点创建集群

初始化完第一个实例后,就可以创建集群了。

# 进入主节点创建集群 mysqlsh root@192.168.65.223:3321 --js # 创建一个 cluster,命名为 'myCluster' var cluster = dba.createCluster('myCluster'); # 创建成功后,查看cluster状态 cluster.status();

当前集群的状态如下

添加副本实例

添加副本实例到创建好的集群

#初始化第二个和第三个实例: cluster.addInstance('root@mgr-node2:3306'); cluster.addInstance('root@mgr-node3:3306'); #查看cluster状态 cluster.status();

小结:完整的集群创建步骤
#进入主节点 mysqlsh root@mgr-node1:3306 --js #mgr-node1 # 参数权限检查 dba.checkInstanceConfiguration('root@mgr-node1:3306'); # 初始化 dba.configureInstance('root@mgr-node1:3306'); # 创建集群 var cluster = dba.createCluster('myCluster'); #查看cluster状态 cluster.status(); #mgr-node2 # 参数权限检查 dba.checkInstanceConfiguration('root@mgr-node2:3306'); # 初始化 dba.configureInstance('root@mgr-node2:3306'); # 添加副本 cluster.addInstance('root@mgr-node2:3306'); #mgr-node3 # 参数权限检查 dba.checkInstanceConfiguration('root@mgr-node3:3306'); # 初始化 dba.configureInstance('root@mgr-node3:3306'); # 添加副本 cluster.addInstance('root@mgr-node3:3306'); #查看cluster状态 cluster.status();

搭建一主两从集群架构最终效果如下:

注意到集群状态已变为"status": "OK"和"statusText": "Cluster is ONLINE and can tolerate up to ONE failure."。
集群节点状态:
  • ONLINE - 节点状态正常。
  • OFFLINE - 实例在运行,但没有加入任何Cluster。
  • RECOVERING - 实例已加入Cluster,正在同步数据。
  • ERROR - 同步数据发生异常。
  • UNREACHABLE - 与其他节点通讯中断,可能是网络问题,可能是节点crash。
  • MISSING - 节点已加入集群,但未启动group replication
测试数据是否同步
#主节点 mgr-node1 [root@192-168-65-223 ~]# docker exec -it mgr-node1 bash root@mgr-node1:/# mysql -uroot -p123456 mysql> create database test; use test; create table t(x int primary key auto_increment,y int); insert into t(x,y) value(1,1);

注意:如果创建表没有设置主键,会抛出错误:ERROR 3098 (HY000): The table does not comply with the requirements by an external plugin.

# 查看其他节点,数据是否同步 [root@192-168-65-223 ~]# docker exec -it mgr-node2 bash root@mgr-node2:/# mysql -uroot -p123456 mysql> use test; Reading table information for completion of table and column names You can turn off this feature to get a quicker startup with -A Database changed mysql> select * from t; +---+------+ | x | y | +---+------+ | 1 | 1 | +---+------+ 1 row in set (0.00 sec)
测试主从切换
#停掉主节点 [root@192-168-65-223 ~]# docker stop mgr-node1 # 连接到mgr-node2 MySQL mgr-node1:3306 ssl JS > \connect root@mgr-node2:3306 # 获取集群实例 MySQL mgr-node2:3306 ssl JS > var cluster=dba.getCluster(); # 查看集群状态 MySQL mgr-node2:3306 ssl JS > cluster.status() { "clusterName": "myCluster", "defaultReplicaSet": { "name": "default", "primary": "mgr-node2:3306", "ssl": "REQUIRED", "status": "OK_NO_TOLERANCE", "statusText": "Cluster is NOT tolerant to any failures. 1 member is not active.", "topology": { "mgr-node1:3306": { "address": "mgr-node1:3306", "memberRole": "SECONDARY", "mode": "n/a", "readReplicas": {}, "role": "HA", "shellConnectError": "MySQL Error 2003: Could not open connection to 'mgr-node1:3306': Can't connect to MySQL server on 'mgr-node1:3306' (113)", "status": "(MISSING)" }, "mgr-node2:3306": { "address": "mgr-node2:3306", "memberRole": "PRIMARY", "mode": "R/W", "readReplicas": {}, "replicationLag": null, "role": "HA", "status": "ONLINE", "version": "8.0.27" }, "mgr-node3:3306": { "address": "mgr-node3:3306", "memberRole": "SECONDARY", "mode": "R/O", "readReplicas": {}, "replicationLag": null, "role": "HA", "status": "ONLINE", "version": "8.0.27" } }, "topologyMode": "Single-Primary" }, "groupInformationSourceMember": "mgr-node2:3306"

可以看到mgr-node2升级为主节点

# 启动mgr-node1节点 [root@192-168-65-223 ~]# docker start mgr-node1 # 查看集群状态,发现mgr-node1正在恢复,最终正常 MySQL mgr-node2:3306 ssl JS > cluster.status() { "clusterName": "myCluster", "defaultReplicaSet": { "name": "default", "primary": "mgr-node2:3306", "ssl": "REQUIRED", "status": "OK_NO_TOLERANCE", "statusText": "Cluster is NOT tolerant to any failures. 1 member is not active.", "topology": { "mgr-node1:3306": { "address": "mgr-node1:3306", "instanceErrors": [ "NOTE: group_replication is stopped." ], "memberRole": "SECONDARY", "memberState": "OFFLINE", "mode": "R/O", "readReplicas": {}, "role": "HA", "status": "(MISSING)", "version": "8.0.27" }, "mgr-node2:3306": { "address": "mgr-node2:3306", "memberRole": "PRIMARY", "mode": "R/W", "readReplicas": {}, "replicationLag": null, "role": "HA", "status": "ONLINE", "version": "8.0.27" }, "mgr-node3:3306": { "address": "mgr-node3:3306", "memberRole": "SECONDARY", "mode": "R/O", "readReplicas": {}, "replicationLag": null, "role": "HA", "status": "ONLINE", "version": "8.0.27" } }, "topologyMode": "Single-Primary" }, "groupInformationSourceMember": "mgr-node2:3306" } MySQL mgr-node2:3306 ssl JS > cluster.status() { "clusterName": "myCluster", "defaultReplicaSet": { "name": "default", "primary": "mgr-node2:3306", "ssl": "REQUIRED", "status": "OK", "statusText": "Cluster is ONLINE and can tolerate up to ONE failure.", "topology": { "mgr-node1:3306": { "address": "mgr-node1:3306", "memberRole": "SECONDARY", "mode": "R/O", "readReplicas": {}, "replicationLag": null, "role": "HA", "status": "ONLINE", "version": "8.0.27" }, "mgr-node2:3306": { "address": "mgr-node2:3306", "memberRole": "PRIMARY", "mode": "R/W", "readReplicas": {}, "replicationLag": null, "role": "HA", "status": "ONLINE", "version": "8.0.27" }, "mgr-node3:3306": { "address": "mgr-node3:3306", "memberRole": "SECONDARY", "mode": "R/O", "readReplicas": {}, "replicationLag": null, "role": "HA", "status": "ONLINE", "version": "8.0.27" } }, "topologyMode": "Single-Primary" }, "groupInformationSourceMember": "mgr-node2:3306" }
更多的常见操作
参数配置
可以用cluster.options()查看当前集群的配置属性,集群参数配置分为两种方式:
  • cluster.setOption() 用来设置所有节点的参数
  • cluster.setInstanceOption() 用来对指定节点配置属性
# 将所有节点的权重都改为50 var cluster = dba.getCluster() cluster.setOption("memberWeight",50) # 重新加入集群重试次数改为5次 cluster.setOption("autoRejoinTries",5) # 将其中一个节点的权重改为75 cluster.setInstanceOption("mgr-node2:3306","memberWeight",75) # 重新加入集群重试次数改为10次 cluster.setInstanceOption("mgr-node2:3306","autoRejoinTries",10)
配置节点权重

memberWeight选项的值域为0到100之间的整数,缺省值为50。该值是故障转移时自动选举主节点的百分比权重,具有较高memberWeight值的实例更有可能在单主群集中被选为主节点

// 查看集群的参数配置(包括memberWeight优先级配置) cluster.options() // 在集群创建时配置 dba.createCluster('myCluster', {memberWeight:75}) // 第一个节点配置方式 var cluster = dba.getCluster() cluster.addInstance('mgr-node2:3306',{memberWeight:50}) cluster.addInstance('mgr-node3:3306',{memberWeight:25}) // 在集群创建完成后修改权重 var cluster = dba.getCluster() cluster.setInstanceOption('mgr-node1:3306','memberWeight',100) cluster.setInstanceOption('mgr-node2:3306','memberWeight',50) cluster.setInstanceOption('mgr-node3:3306','memberWeight',25)
将节点重新加入集群

状态为mssing的节点,通常是组复制关闭或中断状态,可以用cluster.rejoinInstance()重新加入集群,会重新对该节点设置MGR相关参数(持久化到mysqld-auto.conf中)

cluster.removeInstance('root@hostname:3306',{force:true});

如果一些参数做了修改,如server_uuid变更,导致rejoin失败,则需要将节点从集群中删除后重新加入

cluster.removeInstance("root@hostname:3306",{force:true}) cluster.rescan() cluster.addInstance("root@hostname:3306")
集群多数节点异常,恢复

当集群多个节点异常,则失去了仲裁机制,剩下的一个节点

// 将集群剥离为单节点运行 JS > cluster.forceQuorumUsingPartitionOf("root@hostname:3306") // 重新加另外2个节点加入 JS > cluster.rejoinInstance("root@hostname2:3306") JS > cluster.rejoinInstance("root@hostname3:3306")
集群节点角色切换
在MGR的管理下提供了一下3种方式进行角色切换,mysqlsh对其进行了封装调用
  • group_replication_set_as_primary(member_uuid);
    • cluster.setPrimaryInstance("homename:3306")
  • group_replication_switch_to_single_primary_mode()
    • cluster.switchToSinglePrimaryMode("homename:3306")
  • group_replication_switch_to_multi_primary_mode()
    • cluster.switchToMultiPrimaryMode()
单主模式-指定主节点切换
var cluster = dba.getCluster() cluster.setPrimaryInstance('homename:3306') cluster.status()
单主模式和多主模式相互切换
// 切换为多主模式 var cluster = dba.getCluster() cluster.switchToMultiPrimaryMode() // 指定明确的主节点将多主模式切换为单主模式 cluster.switchToSinglePrimaryMode("homename:3306")

将单主模式切换为多主模式的效果

销毁集群

删除与群集关联的所有元数据和配置,并禁用实例上的组复制,但不会删除在实例之间复制的任何数据。要再次创建集群,使用dba.createCluster()

var cluster = dba.getCluster() cluster.dissolve()
创建集群管理用户
cluster.setupAdminAccount('fox')

# 经典MySQL协议连接 mysqlsh --mysql -hmgr-node1 -ufox # X协议连接 mysqlsh --mysqlx -hmgr-node1 -ufox

7. 使用MySQL Router连接集群

配置路由器
mysqlrouter --bootstrap root@mgr-node2:3306 --force --user=root #或者指定host mysqlrouter --bootstrap root@mgr-node2:3306 --force --user=root --report-host mgr

注意,如果用户之前为该实例配置过路由,则可以通过指定force选项强制引导启动。

上面的内容是引导启动路由器时输出的信息,信息提示,MySQL经典协议使用6446端口和6447端口,X协议使用6448端口和6449端口,每种协议使用的两个端口分别用于读写和只读。

在一个运行的集群中,AdminAPI 可以引导多个路由器。用户可以使用cluster.listRouters()方法显示所有注册的路由器列表。

启动路由器
mysqlrouter &

路由器已经成功启动。现在,使用MySQL Shell连接路由器进行验证。

#连接mysqlrouter [root@192-168-65-223 ~]# mysqlsh root@localhost:6446 --sql MySQL localhost:6446 ssl SQL > use test; MySQL localhost:6446 ssl test SQL > select * from t;

查看集群成员信息

MySQL localhost:6446 ssl test SQL > select * from performance_schema.replication_group_members;

测试

测试读写端口6446

用户可以通过连接本机的6446端口连接到MySQL实例

6446为读写端口,也可以插入数据

测试只读端口6647:插入数据报错

MySQL InnoDB ReplicaSet

一、基本概述

MySQL Innodb Cluster = MySQL Shell + MySQL Router + MySQL Group Replication(MGR),全程由 MySQL Shell 来管理操作 MGR 的聚合套件。MySQL 8.0.19 发布后,这种组合延伸到 MySQL Replication(主从复制),也就是 MySQL Shell + MySQL Router + MySQL Replication。
InnoDB ReplicaSet至少由两个MySQL服务器实例组成,并提供用户熟知的主从复制功能,例如读取横向扩展和数据安全性。InnoDB ReplicaSet使用以下MySQL技术。
  • MySQL Shell:MySQL的高级客户端、管理工具,可以用来管理复制集。
  • MySQL复制:一组MySQL实例,通过复制能够提供可用性和异步读取的横向扩展。
  • MySQL Router:一种轻量级的中间件,可在应用程序和InnoDB ReplicaSet之间提供透明的路由。InnoDB ReplicaSet的接口类似于InnoDB Cluster,用户可以利用MySQL Shell使用MySQL实例和MySQL Router。
与InnoDB集群相比,InnoDB ReplicaSet具有多个限制,因此,官方建议尽可能部署InnoDB群集。通常,InnoDB ReplicaSet本身不能提供高可用性。InnoDB ReplicaSet的限制包括:
  • 没有自动故障转移。如果主服务器不可用,则需要使用AdminAPI手动触发故障转移,然后才能再次进行任何更改。但是,辅助实例仍然可用于读取。
  • 无法防止因意外停止或不可用而导致部分数据丢失。暂停之前尚未应用的事务可能会丢失。
  • 无法防止崩溃或不可用后出现不一致情况。如果故障转移在辅助节点仍可用的情况下提升了辅助节点(例如,由于网络分区),则可能会因脑裂而引起不一致。

二、搭建一主一从的复制集

1. 安装2个数据库实例

可以利用docker快速部署2个MySQL实例

主机名(角色)

server_id

宿主机IP

容器固定IP

DB Port

rs-node1(primary)

21

192.168.65.223

172.20.0.20

3331>3306

rs-node2(Secondary)

22

192.168.65.223

172.20.0.21

3332>3306

# 创建组复制的网络 保证三个mysql容器之间可以通过容器名访问 docker network create --driver bridge --subnet 172.20.0.0/24 --gateway 172.20.0.1 rs-network mkdir -p /mysql/rs/node1/data /mysql/rs/node1/conf /mysql/rs/node1/log mkdir -p /mysql/rs/node2/data /mysql/rs/node2/conf /mysql/rs/node2/log #以rs-node1配置为例,创建/mysql/rs/node1/conf/custom.cnf,添加以下配置: vim /mysql/rs/node1/conf/custom.cnf [mysql] # 设置mysql客户端默认编码 default-character-set=utf8 [mysqld] #指定sever_id,多个Mysql实例需要分别改为对应的sever_id server_id=21 # 必须开启GTID支持 gtid_mode=ON enforce_gtid_consistency=ON # 启用二进制日志 log-bin=mysql-bin #启用并行复制 binlog_transaction_dependency_tracking=WRITESET replica_preserve_commit_order=ON replica_parallel_type=LOGICAL_CLOCK transaction_write_set_extraction=XXHASH64 # rs-node2同上,注意配置文件路径和修改server_id vim /mysql/rs/node2/conf/custom.cnf [mysql] # 设置mysql客户端默认编码 default-character-set=utf8 [mysqld] #指定sever_id,多个Mysql实例需要分别改为对应的sever_id server_id=22 # 必须开启GTID支持 gtid_mode=ON enforce_gtid_consistency=ON # 启用二进制日志 log-bin=mysql-bin #启用并行复制 binlog_transaction_dependency_tracking=WRITESET replica_preserve_commit_order=ON replica_parallel_type=LOGICAL_CLOCK transaction_write_set_extraction=XXHASH64 #运行mysql容器 # 为了便于测试,启动容器时指定好IP、hostname docker run -d \ --name rs-node1 \ --privileged=true \ --restart=always \ --ip 172.20.0.20 \ --hostname rs-node1 \ --add-host rs-node2:172.20.0.21 \ --network rs-network \ -p 3331:3306 \ -v /mysql/rs/node1/data:/var/lib/mysql \ -v /mysql/rs/node1/conf:/etc/mysql/conf.d \ -v /mysql/rs/node1/log:/logs \ -e MYSQL_ROOT_PASSWORD=123456 \ -e TZ=Asia/Shanghai mysql:8.0.27 \ --lower_case_table_names=1 docker run -d \ --name rs-node2 \ --privileged=true \ --restart=always \ --ip 172.20.0.21 \ --hostname rs-node2 \ --add-host rs-node1:172.20.0.20 \ --network rs-network \ -p 3332:3306 \ -v /mysql/rs/node2/data:/var/lib/mysql \ -v /mysql/rs/node2/conf:/etc/mysql/conf.d \ -v /mysql/rs/node2/log:/logs \ -e MYSQL_ROOT_PASSWORD=123456 \ -e TZ=Asia/Shanghai mysql:8.0.27 \ --lower_case_table_names=1 # 在宿主机上配置mysql容器的ip和host映射 vim /etc/hosts 172.20.0.20 rs-node1 172.20.0.21 rs-node2

所有实例分别配置远程访问

# 以node1为例 docker exec -it rs-node1 /bin/bash mysql -u root -p123456 #进入mysql执行 ALTER USER 'root'@'%' IDENTIFIED WITH mysql_native_password BY '123456'; flush privileges;

2. 配置复制集

1)初始化主节点,创建复制集

#进入主节点 mysqlsh root@rs-node1:3306 --js # 初始化 dba.configureReplicaSetInstance('root@rs-node1:3306') # 创建复制集,使用异步复制 var rs = dba.createReplicaSet("myrs") #查看状态 rs.status()

2)添加副本节点

#将实例添加到复制集 rs.addInstance('root@rs-node2:3306')

测试数据是否同步

#主节点 rs-node1 [root@192-168-65-223 ~]# docker exec -it rs-node1 bash root@mgr-node1:/# mysql -uroot -p123456 mysql> create datebase test; use test; create table t(x int primary key auto_increment,y int); insert into t(x,y) value(1,1); select * from t; # 进入从节点rs-node2,查看数据是否同步过来 [root@192-168-65-223 ~]# docker exec -it rs-node2 bash root@rs-node2:/# mysql -uroot -p123456 mysql: [Warning] Using a password on the command line interface can be insecure. Welcome to the MySQL monitor. Commands end with ; or \g. Your MySQL connection id is 1596 Server version: 8.0.27 MySQL Community Server - GPL Copyright (c) 2000, 2021, Oracle and/or its affiliates. Oracle is a registered trademark of Oracle Corporation and/or its affiliates. Other names may be trademarks of their respective owners. Type 'help;' or '\h' for help. Type '\c' to clear the current input statement. mysql> use test; Reading table information for completion of table and column names You can turn off this feature to get a quicker startup with -A Database changed mysql> select * from t; +---+------+ | x | y | +---+------+ | 1 | 1 | +---+------+ 1 row in set (0.00 sec)

3. 配置 MySQL Router 路由器

[root@192-168-65-223 ~]# mysqlrouter --bootstrap root@rs-node1:3306 --force --user=root

重启Mysql Router

[root@192-168-65-223 ~]# ps -ef|grep mysqlrouter root 16993 14238 6 11:30 pts/1 00:18:01 mysqlrouter root 21637 14178 0 16:22 pts/0 00:00:00 grep --color=auto mysqlrouter [root@192-168-65-223 ~]# kill -9 16993 # 启动Mysql Router [root@192-168-65-223 ~]# mysqlrouter &

4. 测试

用户可以通过连接本机的6446端口连接到MySQL实例

[root@192-168-65-223 ~]# mysqlsh root@localhost:6446 --sql # 可以查询到插入的测试数据 MySQL localhost:6446 ssl SQL > select * from test.t; +---+---+ | x | y | +---+---+ | 1 | 1 | +---+---+
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/2/13 10:18:20

【突破性】动态环境导航:YOPO自动驾驶规划器全栈应用指南

【突破性】动态环境导航:YOPO自动驾驶规划器全栈应用指南 【免费下载链接】YOPO You Only Plan Once: A Learning Based Quadrotor Planner 项目地址: https://gitcode.com/gh_mirrors/yo/YOPO 传统规划器在动态障碍物场景中面临三大局限:多阶段处…

作者头像 李华
网站建设 2026/2/4 21:55:07

Qwen3-Embedding-0.6B部署报错?常见问题排查与GPU适配解决方案

Qwen3-Embedding-0.6B部署报错?常见问题排查与GPU适配解决方案 1. Qwen3-Embedding-0.6B:轻量高效嵌入模型的核心价值 Qwen3 Embedding 模型系列是 Qwen 家族的最新专有模型,专门设计用于文本嵌入和排序任务。基于 Qwen3 系列的密集基础模型…

作者头像 李华
网站建设 2026/2/16 4:35:47

知识平权:打破信息壁垒的数字阅读自由实践

知识平权:打破信息壁垒的数字阅读自由实践 【免费下载链接】medium-parser-extension Read medium.com using google web cache/archive.is 项目地址: https://gitcode.com/gh_mirrors/me/medium-parser-extension 当优质内容被付费墙阻隔时,我们…

作者头像 李华
网站建设 2026/2/14 17:15:29

Qwen-Image-Layered实战:一张图秒变可编辑PSD图层

Qwen-Image-Layered实战:一张图秒变可编辑PSD图层 Qwen-Image-Layered 不是又一个“AI修图工具”,而是一次对图像编辑范式的重新定义。它不加滤镜、不调参数、不拼接元素,而是把一张静态图片“拆开”——像打开Photoshop的图层面板那样&…

作者头像 李华
网站建设 2026/2/16 22:27:20

工业场景下USB驱动稳定性优化:完整指南

以下是对您提供的技术博文《工业场景下USB驱动稳定性优化:完整技术分析指南》的 深度润色与重构版本 。本次优化严格遵循您的全部要求: ✅ 彻底去除AI痕迹,语言风格贴近一线嵌入式/Linux内核工程师的真实表达; ✅ 摒弃模板化结…

作者头像 李华
网站建设 2026/2/11 0:16:31

如何驯服混乱的菜单栏?2025年Mac效率工具深度测评

如何驯服混乱的菜单栏?2025年Mac效率工具深度测评 【免费下载链接】Ice Powerful menu bar manager for macOS 项目地址: https://gitcode.com/GitHub_Trending/ice/Ice 痛点诊断:Mac菜单栏混乱的三大根源 Mac菜单栏作为系统与用户交互的重要界面…

作者头像 李华