基本概述
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实例

# 创建组复制的网络 保证三个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
|---------------------|-----------|----------------|-------------|------------|
| 主机名(角色) | 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 |
所有实例分别配置远程访问
# 以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 |
+---+---+