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/

相关推荐
锐策4 小时前
〔 MySQL 〕数据库基础
数据库·mysql
日月星宿~5 小时前
【MySQL】summary
数据库·mysql
希忘auto6 小时前
详解MySQL安装
java·mysql
运维佬6 小时前
在 MySQL 8.0 中,SSL 解密失败,在使用 SSL 加密连接时出现了问题
mysql·adb·ssl
Runing_WoNiu7 小时前
MySQL与Oracle对比及区别
数据库·mysql·oracle
天道有情战天下7 小时前
mysql锁机制详解
数据库·mysql
CodingBrother7 小时前
MySQL 中单列索引与联合索引分析
数据库·mysql
布川ku子8 小时前
[2024最新] java八股文实用版(附带原理)---Mysql篇
java·mysql·面试
晴天飛 雪8 小时前
Spring Boot MySQL 分库分表
spring boot·后端·mysql
yc_xym9 小时前
【MySQL】MySQL基础知识复习(上)
数据库·mysql