dble数据库中间件实现MySQL读写分离
1.dble简介
1.1 简介
dble
是企业级开源分布式中间件,江湖人送外号 “MyCat Plus
”;以其简单稳定,持续维护,良好的社区环境和广大的群众基础得到了社区的大力支持;开源地址
dble
存在以下几个优势特性:
- 数据水平拆分 随着业务的发展,您可以使用dble来替换原始的单个MySQL实例。
- 兼容Mysql 与MySQL协议兼容,在大多数情况下,您可以用它替换MySQL来为你的应用程序提供新的存储,而无需更改任何代码。
- 高可用性 dble服务器可以用作集群,业务不会受到单节点故障的影响。
- SQL支持 支持SQL 92标准和MySQL方言。我们支持复杂的SQL查询,如group by,order by,distinct,join,union,sub-query等等。
- 复杂查询优化 优化复杂查询,包括但不限于全局表连接分片表,ER关系表,子查询,简化选择项等。
- 分布式事务支持 使用两阶段提交的分布式事务。您可以为了性能选择普通模式或者为了数据安全采用XA模式。当然,XA模式依赖于MySQL-5.7的XA Transaction,MySQL节点的高可用性和数据的可靠性。
1.2 整体架构
我们首先来看架构图,外部应用通过NIO/AIO进行连接操作。这里首先我们得介绍一下NIO/AIO是什么概念。
BIO 即传统的Blocking I/O,是JDK1.4之前的唯一选择。同步阻塞I/O模式
,并发处理能力低。
NIO 也叫Non-Blocking I/O,在JDK1.4版本之后发布的新功能,同步非阻塞模式
。
AIO 也叫Asynchronous I/O,在JDK1.7版本之后才支持,是异步非阻塞I/O模型
。
可以看到应用发起之后,首先经过NIO操作来到SQL Parse层进行解析。SQL解析生产执行计划,然后路由下发到各个底层MySQL Sharding数据库中执行,这个后台执行的过程也是通过NIO/AIO来实现的。底层各个数据库执行完成之后再返回到中间层进行合并、过滤、分组、排序等操作,最终在返回给客户端。
2.读写分离介绍
2.1 工作原理
基本的原理是让主数据库处理事务性增、删、改操作(INSERT
、DELETE
、UPDATE
),而从数据库处理SELECT
查询操作。数据库复制被用来把事务性操作导致的变更同步到集群中的从数据库。
2.2 为什么要读写分离
- 面对越来越大的访问压力,单台的服务器性能成为瓶颈,需要分担负载。
- 因为大部分业务场景都是读多写少,单数据库实例的性能瓶颈有限(主要集中在磁盘IO),为提升读的效率,需要增加更多的读服务器实例提升读性能。
2.3 什么时候要读写分离
数据库不一定要读写分离,如果程序使用数据库较多时,而写少,读多的情况下会考虑使用。利用数据库主从同步,再通过读写分离可以分担数据库压力,提高性能。
2.4 主从复制与读写分离
在实际的生产环境中,对数据库的读和写都在同一个数据库服务器中,是不能满足实际需求的。无论是在安全性、高可用性还是高并发等各个方面都是完全不能满足实际需求的。
因此,通过主从复制的方式来同步数据,再通过读写分离来提升数据库的并发负载能力。有点类似于rsync,但是不同的是rsync是对磁盘文件做备份,而mysql主从复制是对数据库中的数据、语句做备份。
2.5 mysql支持的复制类型
STATEMENT
:基于语句的复制。在服务器上执行sql语句,在从服务器上执行同样的语句,mysql默认采用基于语句的复制,执行效率高。ROW
:基于行的复制。把改变的内容复制过去,而不是把命令在从服务器上执行一遍。MIXED
:混合类型的复制。默认采用基于语句的复制,一旦发现基于语句无法精确复制时,就会采用基于行的复制。
3.dble实现读写分离(中间代理层)
3.1 测试环境规划
服务器 | IP地址 | 说明 |
---|---|---|
DBLE服务器(CentOS7.9) | 192.168.2.181 |
DBLE实例,数据库中间件,负责接收SQL进行路由分发 |
MySQL master服务器(CentOS7.9) | 192.168.2.170 |
MySQL主节点 |
MySQL slave服务器(CentOS7.9) | 192.168.2.170 |
MySQL从节点 |
3.2 DBLE服务器安装 Java 环境
注意:测试
openjdk1.8.275
以上版本无法启动,报错:java.specification.maintenance.version,所以暂时使用openjdk-1.8.275
版本进行安装。
3.2.1 下载OpenJDK二进制包
3.2.2 安装配置OpenJDK
# 创建目录
[root@dble ~]# mkdir -p /usr/local/java && cd /usr/local/java
# 下载
[root@dble java]# wget -c 'https://ds-devops.oss-cn-shenzhen.aliyuncs.com/openjdk/openjdk_x64_linux_8u275b01.tar.gz' -O /usr/local/java/openjdk_x64_linux_8u275b01.tar.gz
# 解压
[root@dble java]# tar -xvf openjdk_x64_linux_8u275b01.tar.gz
# 增加环境变量
[root@dble java]# vim /etc/profile.d/jdk.sh
export JAVA_HOME=/usr/local/java/openjdk-8u275-b01
export CLASSPATH=.:$JAVA_HOME/jre/lib/rt.jar:$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar
export PATH=$JAVA_HOME/bin:$PATH
# 加载环境变量
[root@dble java]# source /etc/profile
# 验证JDK
[root@dble java]# java -version
openjdk version "1.8.0_275"
OpenJDK Runtime Environment (build 1.8.0_275-b01)
OpenJDK 64-Bit Server VM (build 25.275-b01, mixed mode)
3.3 安装配置dble服务
3.3.1 下载dble安装包
# 创建目录
[root@dble ~]# mkdir -p /data && cd /data
# 下载
[root@dble data]# wget -c 'https://github.com/actiontech/dble/releases/download/3.22.07.0%2Ftag/dble-3.22.07.0-20220915063524-java1.8.0_151-linux.tar.gz' -O /data/dble-3.22.07.0-20220915063524-java1.8.0_151-linux.tar.gz
目录 | 说明 |
---|---|
bin |
dble命令:启动、停止、重启等 |
conf |
配置目录 |
lib |
dble引用jar包目录 |
logs |
日志文件目录 |
3.3.2 配置dble
- 复制配置文件,配置文件目录
/data/dble/conf
# 进入配置目录
[root@dble data]# cd /data/dble/conf
# 复制配置文件
# 1.集群配置
cp cluster_template.cnf cluster.cnf
# 2.系统参数配置
cp bootstrap_template.cnf bootstrap.cnf
# 3.数据库配置
cp db_template.xml db.xml
# 4.用户配置
cp user_template.xml user.xml
集群配置
cluster.cnf
# 标记是否开启集群功能,如果开启,需要配置clusterIP,clusterPort,rootPath,clusterID # 这里配置为false clusterEnable=false
系统参数配置
bootstrap.cnf
# 实例名称 -DinstanceName=dw_mysql # 实例id -DinstanceId=1 # 服务器名称 -DserverId=192.168.2.181
数据库配置
db.xml
- 详细参数配置请参考官方文档。
<?xml version="1.0"?> <dble:db xmlns:dble="http://dble.cloud/"> <dbGroup name="dwGroup" rwSplitMode="3" delayThreshold="10"> <heartbeat errorRetryCount="1" timeout="10" keepAlive="60">show slave status</heartbeat> <dbInstance name="master" url="192.168.2.170:3306" user="root" password="123456" maxCon="500" minCon="50" primary="true"> <property name="testOnCreate">false</property> <property name="testOnBorrow">false</property> <property name="testOnReturn">false</property> <property name="testWhileIdle">true</property> <property name="connectionTimeout">30000</property> <property name="connectionHeartbeatTimeout">20</property> <property name="timeBetweenEvictionRunsMillis">30000</property> <property name="idleTimeout">600000</property> <property name="heartbeatPeriodMillis">10000</property> <property name="evictorShutdownTimeoutMillis">10000</property> </dbInstance> <!-- can have multi read instances --> <dbInstance name="slave_1" url="192.168.2.180:3306" user="root" password="123456" readWeight="10" maxCon="1000" minCon="50" primary="false"> <property name="heartbeatPeriodMillis">60000</property> </dbInstance> </dbGroup> </dble:db>
用户配置
user.xml
- 详细参数配置参考官方文档。
<dble:user xmlns:dble="http://dble.cloud/" version="4.0"> <managerUser name="man1" password="123123" maxCon="100"/> <rwSplitUser name="rw_user" password="123456" dbGroup="dwGroup" maxCon="20"/> </dble:user>
3.4 读写分离测试验证
通过 DBLE 管理入口
9066
登录数据库,注意这里我们通过管理入口的show @@dbinstance;
来验证读写分离的状态的正确性;[root@dble dble]# mysql -h127.0.0.1 -P9066 -uroot -p123123 mysql> show @@dbinstance; +----------+---------+--------------+------+------+--------+------+------+-----------+------------+----------+ | DB_GROUP | NAME | HOST | PORT | W/R | ACTIVE | IDLE | SIZE | READ_LOAD | WRITE_LOAD | DISABLED | +----------+---------+--------------+------+------+--------+------+------+-----------+------------+----------+ | dwGroup | master | 192.168.2.170 | 3306 | W | 0 | 50 | 500 | 32 | 0 | false | | dwGroup | slave_1 | 192.168.2.180 | 3306 | R | 0 | 50 | 1000 | 0 | 0 | false | +----------+---------+--------------+------+------+--------+------+------+-----------+------------+----------+ 2 rows in set (0.01 sec)
查询数据库
[root@dble dble]# mysql -h127.0.0.1 -P8066 -urw_user -p123456 mysql> use test; Database changed mysql> select * from users; ......
再次查看管理端查看数据统计
[root@dble dble]# mysql -h127.0.0.1 -P9066 -uroot -p123123 mysql> show @@dbinstance; +----------+---------+--------------+------+------+--------+------+------+-----------+------------+----------+ | DB_GROUP | NAME | HOST | PORT | W/R | ACTIVE | IDLE | SIZE | READ_LOAD | WRITE_LOAD | DISABLED | +----------+---------+--------------+------+------+--------+------+------+-----------+------------+----------+ | dwGroup | master | 192.168.2.170 | 3306 | W | 0 | 50 | 500 | 32 | 0 | false | | dwGroup | slave_1 | 192.168.2.180 | 3306 | R | 0 | 50 | 1000 | 3 | 0 | false | +----------+---------+--------------+------+------+--------+------+------+-----------+------------+----------+ 2 rows in set (0.01 sec)
从 show @@dbinstance;
这个管理命令上我们能够观测到 READ_LOAD
在 slave节点上计数器增加了 3 次,也就是说读流量顺利的下发到了 slave 节点;当然大家也可以通过打开 MySQL 的 general log 来观测读写分离的情况。
4.总结
本文通过读写分离场景来讲解 DBLE 的快速入门,希望通过简单的示例来给大家梳理 DBLE 的基本概念,帮助大家快速熟悉和使用 DBLE 这个中间件;更高阶的使用方法和细节建议大家参考官方文档。