文章目录
- 前言
- 1. 安装部署
- 1.1 下载安装包
- 1.2 MySQL Shell
- 1.3 配置 MySQL 实例
- 1.4 启动 ReplicaSet
- 1.5 启动 8.2 Router
- 2. 测试路由
- 总结
前言
MySQL 8.0 官方推出过一个高可用方案 ReplicaSet 主要由 Router、MySQL Shell、MySQL Server 三个组件组成。
MySQL Shell 负责管理 ReplicaSet 包括部署、切换、节点加入等,都可以通过内置 AdminAPI 自动化完成。
MySQL Router 是一款轻量级中间件,可在应用程序和 ReplicaSet 之间提供透明路由和读写分离功能。
8.0 时期的 Router 读写需要配置两个端口,应用如果想要使用读写分离的特性,需要额外适配。
-- MySQL 经典协议
- Read/Write Connections: localhost:6446, /data/myrouter/mysql.sock
- Read/Only Connections: localhost:6447, /data/myrouter/mysqlro.sock-- MySQL X 协议
- Read/Write Connections: localhost:6448, /data/myrouter/mysqlx.sock
- Read/Only Connections: localhost:6449, /data/myrouter/mysqlxro.sock
到了 MySQL 8.2 版本 Router 自动可以识别读取和写入,按照配置规则分配到不同的实例,无需使用额外端口。
1. 安装部署
让我们一起从 0 部署一套 MySQL 8.2 ReplicaSet 集群吧 !
- 系统版本:CentOS Linux release 7.8.2003 (Core)
- MySQL Server:8.0.32
IP | hostname | Role |
---|---|---|
172.16.104.56 | 172-16-104-56 | Master |
172.16.104.57 | 172-16-104-56 | Secondary |
vi /etc/hosts
172.16.104.56 172-16-104-56
172.16.104.57 172-16-104-57
1.1 下载安装包
MySQL 官网下载地址:https://downloads.mysql.com/archives/community
压缩包里面包含 MySQL Server 和 MySQL Router 组件。安装 MySQL Server 步骤参考下文👇
MySQL 部署:MySQL 自动化安装部署
1.2 MySQL Shell
官方下载地址:MySQL Shell download
mv mysql-shell-8.0.31-linux-glibc2.12-x86-64bit /usr/local/mysqlsh
export PATH=/usr/local/mysqlsh/bin/:$PATH
echo 'PATH=$PATH:/usr/local/mysqlsh/bin/' >> /etc/profile
进入 MySQL Shell 使用 \py & \js 可以切换命令模式,本篇文章使用 python 模式演示:
1.3 配置 MySQL 实例
部署好 MySQL 实例后,需要创建一个用户,提供给 MySQL Shell 使用,这里演示创建的用户是:rw_shell
GRANT CLONE_ADMIN, CONNECTION_ADMIN, CREATE USER, EXECUTE, FILE, GROUP_REPLICATION_ADMIN, PERSIST_RO_VARIABLES_ADMIN, PROCESS, RELOAD, REPLICATION CLIENT, REPLICATION SLAVE, REPLICATION_APPLIER, REPLICATION_SLAVE_ADMIN, ROLE_ADMIN, SELECT, SHUTDOWN, SYSTEM_VARIABLES_ADMIN ON *.* TO 'rw_shell'@'%' WITH GRANT OPTION;
GRANT DELETE, INSERT, UPDATE ON mysql.* TO 'rw_shell'@'%' WITH GRANT OPTION;
GRANT ALTER, ALTER ROUTINE, CREATE, CREATE ROUTINE, CREATE TEMPORARY TABLES, CREATE VIEW, DELETE, DROP, EVENT, EXECUTE, INDEX, INSERT, LOCK TABLES, REFERENCES, SHOW VIEW, TRIGGER, UPDATE ON mysql_innodb_cluster_metadata.* TO 'rw_shell'@'%' WITH GRANT OPTION;
GRANT ALTER, ALTER ROUTINE, CREATE, CREATE ROUTINE, CREATE TEMPORARY TABLES, CREATE VIEW, DELETE, DROP, EVENT, EXECUTE, INDEX, INSERT, LOCK TABLES, REFERENCES, SHOW VIEW, TRIGGER, UPDATE ON mysql_innodb_cluster_metadata_bkp.* TO 'rw_shell'@'%' WITH GRANT OPTION;
GRANT ALTER, ALTER ROUTINE, CREATE, CREATE ROUTINE, CREATE TEMPORARY TABLES, CREATE VIEW, DELETE, DROP, EVENT, EXECUTE, INDEX, INSERT, LOCK TABLES, REFERENCES, SHOW VIEW, TRIGGER, UPDATE ON mysql_innodb_cluster_metadata_previous.* TO 'rw_shell'@'%' WITH GRANT OPTION;
配置 MySQL 实例,检查是否符合创建 ReplicaSet 的条件,如果发现需要修改的地方,就会提示确认修改。
执行次命令会让用户输入密码,保存后会进入检查阶段。
dba.configure_replica_set_instance('rw_shell@172-16-104-55:3306', {"clusterAdmin": "rw_shell@'%'"})
dba.configure_replica_set_instance('rw_shell@172-16-104-56:3306', {"clusterAdmin": "rw_shell@'%'"})
MySQL Shell 会检查数据库参数是否满足创建 ReplicaSet 条件,并提出修改建议:
此阶段执行完成后,表示实例都具备组成 ReplicaSet 条件,可进入下一步。
1.4 启动 ReplicaSet
使用 MySQL Shell 连接到主实例,否则测试中会报 session 错误。
An open session is required to perform this operation.
\c rw_shell@172-16-104-56:3306
创建 ReplicaSet 默认当前进入的实例为主库实例:
rs = dba.create_replica_set("prd_op_service")
添加复制节点:
rs.add_instance("172-16-104-57:3306")
至此,ReplicaSet 已配置完成,下图为拓扑信息:
{"replicaSet": {"name": "prd_op_service", "primary": "172-16-104-56:3306", "status": "AVAILABLE", "statusText": "All instances available.", "topology": {"172-16-104-56:3306": {"address": "172-16-104-56:3306", "instanceRole": "PRIMARY", "mode": "R/W", "status": "ONLINE"}, "172-16-104-57:3306": {"address": "172-16-104-57:3306", "instanceRole": "SECONDARY", "mode": "R/O", "replication": {"applierStatus": "APPLIED_ALL", "applierThreadState": "Waiting for an event from Coordinator", "applierWorkerThreads": 4, "receiverStatus": "ON", "receiverThreadState": "Waiting for source to send event", "replicationLag": null, "replicationSsl": "TLS_AES_128_GCM_SHA256 TLSv1.3", "replicationSslMode": "REQUIRED"}, "status": "ONLINE"}}, "type": "ASYNC"}
}
1.5 启动 8.2 Router
解压二进制包,开箱即用。
xz -d mysql-router-8.2.0-linux-glibc2.12-x86_64.tar.xz
tar -xvf mysql-router-8.2.0-linux-glibc2.12-x86_64.tar
创建 router 专用用户:
rs.setup_router_account('op_router')
更新 router 配置信息:
./mysqlrouter \--bootstrap rw_shell@172-16-104-56:3306 \--directory /data/myrouter \--conf-use-sockets \--account op_router \--user=root
此时 Router 输出的配置信息:
After this MySQL Router has been started with the generated configuration$ ./mysqlrouter -c /data/myrouter/mysqlrouter.confInnoDB ReplicaSet 'prd_op_service' can be reached by connecting to:## MySQL Classic protocol- Read/Write Connections: localhost:6446, /data/myrouter/mysql.sock
- Read/Only Connections: localhost:6447, /data/myrouter/mysqlro.sock
- Read/Write Split Connections: localhost:6450, /data/myrouter/mysqlsplit.sock## MySQL X protocol- Read/Write Connections: localhost:6448, /data/myrouter/mysqlx.sock
- Read/Only Connections: localhost:6449, /data/myrouter/mysqlxro.sock
从输出结果看,相比于之前的版本,多了一个 6450 端口。
启动 mysqlrouter 服务:
./mysqlrouter -c /data/myrouter/mysqlrouter.conf &
2. 测试路由
使用 6450 端口连接 MySQL:
mysql -urw_shell -P6450 -h172.16.104.56 -p
rw_shell@mysql 17:21: [(none)]>select @@hostname;
+---------------+
| @@hostname |
+---------------+
| 172-16-104-57 |
+---------------+
1 row in set (0.01 sec)rw_shell@mysql 17:22: [(none)]>begin;
Query OK, 0 rows affected (0.01 sec)rw_shell@mysql 17:22: [(none)]>select @@hostname;
+---------------+
| @@hostname |
+---------------+
| 172-16-104-56 |
+---------------+
1 row in set (0.01 sec)rw_shell@mysql 17:22: [(none)]>commit;
Query OK, 0 rows affected (0.00 sec)rw_shell@mysql 17:22: [(none)]>
rw_shell@mysql 17:22: [(none)]>select @@hostname;
+---------------+
| @@hostname |
+---------------+
| 172-16-104-57 |
+---------------+
1 row in set (0.01 sec)
从上面的实验,我们可以看到,默认情况下,如果执行读取操作,我们将到达复制节点,但如果启动事务,我们将到主节点,而无需更改端口并使用相同的连接。
rw_shell@mysql 17:25: [(none)]>select @@hostname;
+---------------+
| @@hostname |
+---------------+
| 172-16-104-57 |
+---------------+
1 row in set (0.01 sec)rw_shell@mysql 17:25: [(none)]>start transaction read only;
Query OK, 0 rows affected (0.02 sec)rw_shell@mysql 17:26: [(none)]>select @@hostname;
+---------------+
| @@hostname |
+---------------+
| 172-16-104-57 |
+---------------+
1 row in set (0.01 sec)
启动事务类型为只读事务的话,也会直接到复制节点。
rw_shell@mysql 17:32: [(none)]>ROUTER SET access_mode='read_only';
Query OK, 0 rows affected (0.00 sec)rw_shell@mysql 17:32: [(none)]>select @@hostname;
+---------------+
| @@hostname |
+---------------+
| 172-16-104-57 |
+---------------+
1 row in set (0.02 sec)rw_shell@mysql 17:33: [(none)]>ROUTER SET access_mode='read_write';
Query OK, 0 rows affected (0.00 sec)rw_shell@mysql 17:33: [(none)]>select @@hostname;
+---------------+
| @@hostname |
+---------------+
| 172-16-104-56 |
+---------------+
1 row in set (0.02 sec)
可以通过 ROUTER SET 语句,定义接下来 SQL 访问类型。
总结
MySQL 8.2 版本的 router 读写分离支持使用一个端口,无需业务适应更改,是一项非常很有价值的功能,可以优化数据库性能和可扩展性,而无需对应用程序进行任何更改。
参考资料:https://lefred.be/content/mysql-8-2-transparent-read-write-splitting/