MySQL Shell的AdminAPI新增了 对InnoDB ReplicaSet的支持,可以用与InnoDB Cluster类似的方式管理一组运行基于GTID的异步复制的MySQL实例。InnoDB ReplicaSet由一个主和多个从组成。您可以使用ReplicaSet对象和AdminAPI操作,例如检查InnoDB ReplicaSet的状态,并在发生故障时手动故障转移到新的主数据库。与InnoDB Cluster类似,MySQL Router支持针对InnoDB ReplicaSet的引导,这意味着可以自动配置MySQL Router以使用InnoDB ReplicaSet,而无需手动配置它。这使InnoDB ReplicaSet成为启动和运行MySQL复制和MySQL Router的快速简便方法,使其非常适合横向扩展读取。
与InnoDB Cluster相比,InnoDB ReplicaSet具有如下限制:
IP:PORT | 主机名 | server-id | 系统版本 | MySQL版本 | MySQL Shell版本 | MySQL Router版本 |
---|---|---|---|---|---|---|
192.168.240.81:3310 | innodb_cluster_01 | 81 | CentOS7.6 | 8.0.21 | mysql-shell-8.0.21 | mysql-router-8.0.21 |
192.168.240.82:3310 | innodb_cluster_02 | 82 | CentOS7.6 | 8.0.21 | - | - |
192.168.240.83:3310 | innodb_cluster_03 | 83 | CentOS7.6 | 8.0.21 | - | - |
MySQL Shell ,Rpm包下载地址:https://dev.mysql.com/downloads/shell/
MySQL Router,Rpm包下载地址:https://dev.mysql.com/downloads/router/
MySQL ,二进制包下载地址:https://dev.mysql.com/downloads/mysql/
InnoDB ReplicaSet集群内部节点主机名必须唯一,可以通过hostname命令设置
按照先前规划,填写/etc/hosts文件
[root@localhost ~]# cat /etc/hosts
192.168.240.81 innodb_rs_01
192.168.240.82 innodb_rs_02
192.168.240.83 innodb_rs_03
修改本机主机名(每台机根据情况修改自己主机名)
hostnamectl set-hostname innodb_rs_01
systemctl stop firewalld
setenforce 0
把MySQL二进制安装包上传到/usr/local/src
目录下
cd /usr/local/src
tar xf mysql-8.0.21-linux-glibc2.17-x86_64-minimal.tar.xz
mv mysql-8.0.21-linux-glibc2.17-x86_64-minimal /usr/local/mysql8.0
echo 'export PATH=/usr/local/mysql8.0/bin:$PATH' >> /etc/profile
. /etc/profile
创建目录结构(所有节点)
useradd -M -s /sbin/nologin mysql
mkdir -pv /datadir/{temp,log,data}
chown -R mysql:mysql /datadir
初始化数据库(所有节点)
mysqld --datadir=/datadir/data --user=mysql --initialize-insecure
chown -R mysql:mysql /datadir
修改配置文件(所有节点)
[mysqld]
basedir=/usr/local/mysql8.0
user=mysql
port=3310
datadir=/datadir/data
log-error=/datadir/log/err.log
pid-file=/datadir/temp/mysqld.pid
socket=/datadir/temp/mysqld.sock
symbolic-links=0
server_id=81
gtid-mode=on
enforce-gtid-consistency=true
log_bin=/datadir/log/binlog
binlog_format=ROW
[client]
socket=/datadir/temp/mysqld.sock
只需要修改server_id这一项即可(保证所有MySQL服务器都不同)
启动数据库(所有节点)
mysqld_safe --defaults-file=/etc/my.cnf --daemonize
进入mysql,创建ir用户(所有节点)
set sql_log_bin=OFF;
CREATE USER 'ir'@'%' IDENTIFIED BY '123456';
GRANT ALL ON *.* to 'ir'@'%' WITH GRANT OPTION;
set sql_log_bin=ON;
上传MySQL Shell包到innodb_rs_01
的/usr/local/src目录下
cd /usr/local/src
yum install mysql-shell-8.0.21-1.el7.x86_64.rpm -y
innodb_rs_01
节点执行)mysqlsh
rsadmin
的集群管理员(此处以innodb_rs_01节点为例) MySQL JS > dba.configureReplicaSetInstance('ir@innodb_rs_01:3310', {clusterAdmin: "'rsadmin'@'%'"});
Please provide the password for 'ir@innodb_rs_01:3310': ******* # 此处填写ir用户的密码
Save password for 'ir@innodb_rs_01:3310'? [Y]es/[N]o/Ne[v]er (default No): y # 是否记住密码,如果选择y则下次连接无需重新输入密码
Configuring local MySQL instance listening at port 3310 for use in an InnoDB ReplicaSet...
This instance reports its own address as innodb_rs_01:3310
Clients and other cluster members will communicate with it through this address by default. If this is not correct, the report_host MySQL system variable should be changed.
Password for new account: ******# 此处填写'rsadmin'@'%' 想要设置的密码
Confirm password: ****** # 确认'rsadmin'@'%'密码
The instance 'innodb_rs_01:3310' is valid to be used in an InnoDB ReplicaSet.
Cluster admin user 'rsadmin'@'%' created.
The instance 'innodb_rs_01:3310' is already ready to be used in an InnoDB ReplicaSet. # 表示已经就绪,可以创建innodb ReplicaSet
- dba.configureReplicaSetInstance()函数可以创建管理员帐户。使用正确的权限来创建帐户来管理InnoDB集群和InnoDB副本集。
- 在同一集群或副本集的所有实例中,管理员帐户必须具有相同的用户名和密码。
innodb_rs_01
节点执行)mysql-js> \connect ir@innodb_rs_01:3310
MySQL innodb_rs_01:3310 ssl JS > var rs = dba.createReplicaSet("example")
A new replicaset with instance 'innodb_rs_01:3310' will be created.
* Checking MySQL instance at innodb_rs_01:3310
This instance reports its own address as innodb_rs_01:3310
innodb_rs_01:3310: Instance configuration is suitable.
* Updating metadata...
ReplicaSet object successfully created for innodb_rs_01:3310.
Use rs.addInstance() to add more asynchronously replicated instances to this replicaset and rs.status() to check its status.
innodb_rs_01
节点执行) MySQL innodb_rs_01:3310 ssl JS > rs.status()
{
"replicaSet": {
"name": "example", # 复制集名称
"primary": "innodb_rs_01:3310", # 主节点
"status": "AVAILABLE", # 状态:可用
"statusText": "All instances available.", # 状态备注信息
"topology": { # 当前拓扑
"innodb_rs_01:3310": {
"address": "innodb_rs_01:3310", # 复制集通讯地址
"instanceRole": "PRIMARY", # 角色,主/从
"mode": "R/W", # 模式,主节点可读可写,从节点只读
"status": "ONLINE" # 节点状态
}
},
"type": "ASYNC" # 复制类型 异步
}
}
innodb_rs_02:3310
实例进入集群(innodb_rs_01
节点执行) MySQL innodb_rs_01:3310 ssl JS > rs.addInstance('innodb_rs_02:3310')
Adding instance to the replicaset...
* Performing validation checks
This instance reports its own address as innodb_rs_02:3310
innodb_rs_02:3310: Instance configuration is suitable.
* Checking async replication topology...
* Checking transaction state of the instance...
NOTE: The target instance 'innodb_rs_02:3310' has not been pre-provisioned (GTID set is empty). The Shell is unable to decide whether replication can completely recover its state.
The safest and most convenient way to provision a new instance is through automatic clone provisioning, which will completely overwrite the state of 'innodb_rs_02:3310' with a physical snapshot from an existing replicaset member. To use this method by default, set the 'recoveryMethod' option to 'clone'.
WARNING: It should be safe to rely on replication to incrementally recover the state of the new instance if you are sure all updates ever executed in the replicaset were done with GTIDs enabled, there are no purged transactions and the new instance contains the same GTID set as the replicaset or a subset of it. To use this method by default, set the 'recoveryMethod' option to 'incremental'.
# 输入I,选择增量恢复,需要确保所有实例GTID打开,以及没有被purged的事务,且gitd set必须是主节点的子集
Please select a recovery method [C]lone/[I]ncremental recovery/[A]bort (default Clone): i
* Updating topology
** Configuring innodb_rs_02:3310 to replicate from innodb_rs_01:3310
** Waiting for new instance to synchronize with PRIMARY...
The instance 'innodb_rs_02:3310' was added to the replicaset and is replicating from innodb_rs_01:3310.
innodb_rs_03:3310
实例进入集群(innodb_rs_01
节点执行) MySQL innodb_rs_01:3310 ssl JS > rs.addInstance('innodb_rs_03:3310')
Adding instance to the replicaset...
* Performing validation checks
This instance reports its own address as innodb_rs_03:3310
innodb_rs_03:3310: Instance configuration is suitable.
* Checking async replication topology...
* Checking transaction state of the instance...
NOTE: The target instance 'innodb_rs_03:3310' has not been pre-provisioned (GTID set is empty). The Shell is unable to decide whether replication can completely recover its state.
The safest and most convenient way to provision a new instance is through automatic clone provisioning, which will completely overwrite the state of 'innodb_rs_03:3310' with a physical snapshot from an existing replicaset member. To use this method by default, set the 'recoveryMethod' option to 'clone'.
WARNING: It should be safe to rely on replication to incrementally recover the state of the new instance if you are sure all updates ever executed in the replicaset were done with GTIDs enabled, there are no purged transactions and the new instance contains the same GTID set as the replicaset or a subset of it. To use this method by default, set the 'recoveryMethod' option to 'incremental'.
# 输入I,选择增量恢复,需要确保所有实例GTID打开,以及没有被purged的事务,且gitd set必须是主节点的子集
Please select a recovery method [C]lone/[I]ncremental recovery/[A]bort (default Clone): i
* Updating topology
** Configuring innodb_rs_03:3310 to replicate from innodb_rs_01:3310
** Waiting for new instance to synchronize with PRIMARY...
The instance 'innodb_rs_03:3310' was added to the replicaset and is replicating from innodb_rs_01:3310.
MySQL innodb_rs_01:3310 ssl JS > rs.status()
{
"replicaSet": {
"name": "example",# 复制集名称
"primary": "innodb_rs_01:3310",# 主节点
"status": "AVAILABLE",# 状态:可用
"statusText": "All instances available.", # 状态备注信息
"topology": { # 当前拓扑
"innodb_rs_01:3310": {
"address": "innodb_rs_01:3310", # 复制集通讯地址
"instanceRole": "PRIMARY", # 角色,主/从
"mode": "R/W", # 模式,主节点可读可写,从节点只读
"status": "ONLINE" # 节点状态
},
"innodb_rs_02:3310": {
"address": "innodb_rs_02:3310",
"instanceRole": "SECONDARY",
"mode": "R/O",
"replication": {
"applierStatus": "APPLIED_ALL",
"applierThreadState": "Slave has read all relay log; waiting for more updates",
"receiverStatus": "ON",
"receiverThreadState": "Waiting for master to send event",
"replicationLag": null
},
"status": "ONLINE"
},
"innodb_rs_03:3310": {
"address": "innodb_rs_03:3310",
"instanceRole": "SECONDARY",
"mode": "R/O",
"replication": {
"applierStatus": "APPLIED_ALL",
"applierThreadState": "Slave has read all relay log; waiting for more updates",
"receiverStatus": "ON",
"receiverThreadState": "Waiting for master to send event",
"replicationLag": null
},
"status": "ONLINE"
}
},
"type": "ASYNC" # 复制类型 异步
}
}
上传MySQL Router RPM包innodb_rs_03
节点上的/usr/local/src
目录下
cd /usr/local/src
yum install mysql-router-community-8.0.21-1.el7.x86_64.rpm -y
MySQL Router对接InnoDB Cluster
mysqlrouter --bootstrap ir@innodb_rs_01:3310 --user=mysqlrouter
启动MySQL Router
systemctl start mysqlrouter
会启动4个端口
6446
- 对于传统MySQL协议读写会话,MySQL路由器将传入连接重定向到Primary服务器实例。6447
- 对于传统MySQL协议只读会话,MySQL路由器将传入连接重定向到其中一个从服务器实例。64460
- 对于X协议读写会话,MySQL路由器将传入连接重定向到Primary服务器实例。64470
- 对于X协议只读会话,MySQL路由器将传入连接重定向到其中一个从服务器实例。连接读写端口,进行测试
# mysql -uir -p -P6446 -h192.168.240.83
Enter password:
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 109
Server version: 8.0.21 MySQL Community Server - GPL
Copyright (c) 2000, 2020, Oracle and/or its affiliates. All rights reserved.
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> select @@server_id;
+-------------+
| @@server_id |
+-------------+
| 81 |
+-------------+
1 row in set (0.00 sec)
连接InnoDB 复制集
# 连接其中一个复制集节点
MySQL JS > \c ir@innodb_rs_02:3310
# 获取复制集连接
MySQL innodb_rs_02:3310 ssl JS > var rs = dba.getReplicaSet()
# 后续就可以直接使用rs对象管理集群
查看集群状态
MySQL innodb_rs_02:3310 ssl JS > rs.status()
{
"replicaSet": {
"name": "example",
"primary": "innodb_rs_01:3310",
"status": "AVAILABLE",
"statusText": "All instances available.",
"topology": {
"innodb_rs_01:3310": {
"address": "innodb_rs_01:3310",
"instanceRole": "PRIMARY",
"mode": "R/W",
"status": "ONLINE"
},
"innodb_rs_02:3310": {
"address": "innodb_rs_02:3310",
"instanceRole": "SECONDARY",
"mode": "R/O",
"replication": {
"applierStatus": "APPLIED_ALL",
"applierThreadState": "Slave has read all relay log; waiting for more updates",
"receiverStatus": "ON",
"receiverThreadState": "Waiting for master to send event",
"replicationLag": null
},
"status": "ONLINE"
},
"innodb_rs_03:3310": {
"address": "innodb_rs_03:3310",
"instanceRole": "SECONDARY",
"mode": "R/O",
"replication": {
"applierStatus": "APPLIED_ALL",
"applierThreadState": "Slave has read all relay log; waiting for more updates",
"receiverStatus": "ON",
"receiverThreadState": "Waiting for master to send event",
"replicationLag": null
},
"status": "ONLINE"
}
},
"type": "ASYNC"
}
}
新增实例
# 新增innodb_rs_03:3310节点
MySQL innodb_rs_02:3310 ssl JS > rs.addInstance('innodb_rs_03:3310')
强制切换主节点
# 当主节点down了,就需要强制切换主
rs.forcePrimaryInstance('innodb_rs_03:3310')
设置主节点
MySQL innodb_rs_02:3310 ssl JS > rs.setPrimaryInstance('innodb_rs_03:3310')
innodb_rs_03:3310 will be promoted to PRIMARY of 'example'.
The current PRIMARY is innodb_rs_01:3310.
* Connecting to replicaset instancess
** Connecting to innodb_rs_01:3310
** Connecting to innodb_rs_02:3310
** Connecting to innodb_rs_03:3310
** Connecting to innodb_rs_01:3310
** Connecting to innodb_rs_02:3310
** Connecting to innodb_rs_03:3310
* Performing validation checks
** Checking async replication topology...
** Checking transaction state of the instance...
* Synchronizing transaction backlog at innodb_rs_03:3310
* Updating metadata
* Acquiring locks in replicaset instances
** Pre-synchronizing SECONDARIES
** Acquiring global lock at PRIMARY
** Acquiring global lock at SECONDARIES
* Updating replication topology
** Configuring innodb_rs_01:3310 to replicate from innodb_rs_03:3310
** Changing replication source of innodb_rs_02:3310 to innodb_rs_03:3310
innodb_rs_03:3310 was promoted to PRIMARY.
移除实例
# 从ReplicaSet中移除innodb_rs_03:3310节点
MySQL innodb_rs_02:3310 ssl JS > rs.removeInstance('innodb_rs_03:3310')
查看MySQL Router信息
MySQL innodb_rs_02:3310 ssl JS > rs.listRouters()
{
"replicaSetName": "example",
"routers": {
"innodb_rs_03::system": {
"hostname": "innodb_rs_03",
"lastCheckIn": "2020-08-06 00:09:40",
"roPort": 6447,
"roXPort": 64470,
"rwPort": 6446,
"rwXPort": 64460,
"version": "8.0.21"
}
}
}
)
7. 查看MySQL Router信息
```js
MySQL innodb_rs_02:3310 ssl JS > rs.listRouters()
{
"replicaSetName": "example",
"routers": {
"innodb_rs_03::system": {
"hostname": "innodb_rs_03",
"lastCheckIn": "2020-08-06 00:09:40",
"roPort": 6447,
"roXPort": 64470,
"rwPort": 6446,
"rwXPort": 64460,
"version": "8.0.21"
}
}
}