8.2 新特性 - 透明的读写分离

文章目录

    • 前言
    • [1. 安装部署](#1. 安装部署)
      • [1.1 下载安装包](#1.1 下载安装包)
      • [1.2 MySQL Shell](#1.2 MySQL Shell)
      • [1.3 配置 MySQL 实例](#1.3 配置 MySQL 实例)
      • [1.4 启动 ReplicaSet](#1.4 启动 ReplicaSet)
      • [1.5 启动 8.2 Router](#1.5 启动 8.2 Router)
    • [2. 测试路由](#2. 测试路由)
    • 总结

前言

MySQL 8.0 官方推出过一个高可用方案 ReplicaSet 主要由 Router、MySQL Shell、MySQL Server 三个组件组成。

MySQL Shell 负责管理 ReplicaSet 包括部署、切换、节点加入等,都可以通过内置 AdminAPI 自动化完成。

MySQL Router 是一款轻量级中间件,可在应用程序和 ReplicaSet 之间提供透明路由和读写分离功能。

8.0 时期的 Router 读写需要配置两个端口,应用如果想要使用读写分离的特性,需要额外适配。

python 复制代码
-- 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
bash 复制代码
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

bash 复制代码
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

bash 复制代码
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 的条件,如果发现需要修改的地方,就会提示确认修改。

执行次命令会让用户输入密码,保存后会进入检查阶段。

bash 复制代码
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.

python 复制代码
\c rw_shell@172-16-104-56:3306

创建 ReplicaSet 默认当前进入的实例为主库实例:

python 复制代码
rs = dba.create_replica_set("prd_op_service")

添加复制节点:

python 复制代码
rs.add_instance("172-16-104-57:3306")

至此,ReplicaSet 已配置完成,下图为拓扑信息:

json 复制代码
{
    "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

解压二进制包,开箱即用。

python 复制代码
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 专用用户:

python 复制代码
rs.setup_router_account('op_router')

更新 router 配置信息:

python 复制代码
./mysqlrouter \
   --bootstrap rw_shell@172-16-104-56:3306 \
   --directory /data/myrouter \
   --conf-use-sockets \
   --account op_router \
   --user=root

此时 Router 输出的配置信息:

python 复制代码
After this MySQL Router has been started with the generated configuration

    $ ./mysqlrouter -c /data/myrouter/mysqlrouter.conf

InnoDB 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 服务:

python 复制代码
./mysqlrouter -c /data/myrouter/mysqlrouter.conf &

2. 测试路由

使用 6450 端口连接 MySQL:

python 复制代码
mysql -urw_shell -P6450 -h172.16.104.56 -p
python 复制代码
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)

从上面的实验,我们可以看到,默认情况下,如果执行读取操作,我们将到达复制节点,但如果启动事务,我们将到主节点,而无需更改端口并使用相同的连接。

python 复制代码
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)

启动事务类型为只读事务的话,也会直接到复制节点。

python 复制代码
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/

相关推荐
drebander1 小时前
MySQL 查询优化案例分享
数据库·mysql
小林coding3 小时前
阿里云 Java 后端一面,什么难度?
java·后端·mysql·spring·阿里云
18号房客4 小时前
高级sql技巧进阶教程
大数据·数据库·数据仓库·sql·mysql·时序数据库·数据库架构
翔云1234565 小时前
MySQL purged gtid是如何生成和维护的
数据库·mysql
平行线也会相交7 小时前
云图库平台(三)——后端用户模块开发
数据库·spring boot·mysql·云图库平台
恒辉信达8 小时前
hhdb客户端介绍(53)
数据库·mysql·hhdb·数据库可视化界面客户端
Hello.Reader9 小时前
Redis热点数据管理全解析:从MySQL同步到高效缓存的完整解决方案
redis·mysql·缓存
是程序喵呀9 小时前
MySQL备份
android·mysql·adb
指尖上跳动的旋律9 小时前
shell脚本定义特殊字符导致执行mysql文件错误的问题
数据库·mysql
苹果醋313 小时前
2020重新出发,MySql基础,MySql表数据操作
java·运维·spring boot·mysql·nginx