通过MyCAT中间件实现读写分离

来源:互联网 发布:淘宝客昵称怎么修改 编辑:程序博客网 时间:2024/06/06 01:15
紧接着上一章节的《MySQL一主多从配置》,本章节将介绍如何搭建mycat中间件,并用mycat来做读写分离.

本章概要

1、MyCat关键特性
2、下载MyCat主程序
3、基础设施
4、配置MyCat&验证

Mycat关键特性

关键特性
支持SQL92标准
支持MySQL、Oracle、DB2、SQL Server、PostgreSQL等DB的常见SQL语法
遵守Mysql原生协议,跨语言,跨平台,跨数据库的通用中间件代理。
基于心跳的自动故障切换,支持读写分离,支持MySQL主从,以及galera cluster集群。
支持Galera for MySQL集群,Percona Cluster或者MariaDB cluster
基于Nio实现,有效管理线程,解决高并发问题。
支持数据的多片自动路由与聚合,支持sum,count,max等常用的聚合函数,支持跨库分页。
支持单库内部任意join,支持跨库2表join,甚至基于caltlet的多表join。
支持通过全局表,ER关系的分片策略,实现了高效的多表join查询。
支持多租户方案。
支持分布式事务(弱xa)。
支持XA分布式事务(1.6.5)。
支持全局序列号,解决分布式下的主键生成问题。
分片规则丰富,插件化开发,易于扩展。
强大的web,命令行监控。
支持前端作为MySQL通用代理,后端JDBC方式支持Oracle、DB2、SQL Server 、 mongodb 、巨杉。
支持密码加密
支持服务降级
支持IP白名单
支持SQL黑名单、sql注入攻击拦截
支持prepare预编译指令(1.6)
支持非堆内存(Direct Memory)聚合计算(1.6)
支持PostgreSQL的native协议(1.6)
支持mysql和oracle存储过程,out参数、多结果集返回(1.6)
支持zookeeper协调主从切换、zk序列、配置zk化(1.6)
支持库内分表(1.6)
集群基于ZooKeeper管理,在线升级,扩容,智能优化,大数据处理(2.0开发版)。
什么是MYCAT
一个彻底开源的,面向企业应用开发的大数据库集群
支持事务、ACID、可以替代MySQL的加强版数据库
一个可以视为MySQL集群的企业级数据库,用来替代昂贵的Oracle集群
一个融合内存缓存技术、NoSQL技术、HDFS大数据的新型SQL Server
结合传统数据库和新型分布式数据仓库的新一代企业级数据库产品
一个新颖的数据库中间件产品

以上来源于官方说明,MyCat将在未来协助我们实现MySQL的高可用、高性能集群,并且完全实现了与业务代码解耦,无侵入。

下载MyCat主程序

直接访问http://www.mycat.org.cn/官方地址,可以找到当前最新版本,本案例使用1.6版本实现。目前为WIN64系统进行验证,故直接下载WIN版本解压即可。
注:MyCat依赖JDK环境,故需要确保已经正常安装Jdk。

基础设施

目前本地已经运行有3个实例服务
Master 127.0.0.1:3310
Slave 127.0.0.1:3321
Slave 127.0.0.1:3322
本案例主要验证读写分离,故数据库均为springboot1,且用户名密码均为root。

配置MyCat

Conf目录下存放配置文件:
1、server.xml是Mycat服务器参数调整和用户授权的配置文件;
2、schema.xml是逻辑库定义和表以及分片定义的配置文件;
3、rule.xml是分片规则的配置文件,分片规则的具体一些参数信息单独存放为文件,也在这个目录下,配置文件修改,需要重启Mycat或者通过9066端口reload;
4、wrapper.conf:JVM配置参数等设置;

第一步、我们需要配置的是schema.xml:
<schema name="TESTDB" checkSQLschema="false" sqlMaxLimit="100" dataNode="dn1">
</schema>
<dataNode name="dn1" dataHost="localhost1" database="springboot1" />
<dataHost name="localhost1" maxCon="1000" minCon="10" balance="1"
writeType="0" dbType="mysql" dbDriver="native" switchType="-1" slaveThreshold="100">
<heartbeat>select user()</heartbeat>
<!-- can have multi write hosts -->
<writeHost host="hostM1" url="localhost:3310" user="root"
password="root">
<!-- can have multi read hosts -->
<readHost host="hostS2" url="127.0.0.1:3322" user="root" password="root" />
</writeHost>
<writeHost host="hostS1" url="localhost:3321" user="root"
password="root" />
<!-- <writeHost host="hostM2" url="localhost:3316" user="root" password="123456"/> -->
</dataHost>
主要参数说明:
A、schema:逻辑库,与MySQL中的Database(数据库)对应,一个逻辑库中定义了所包括的Table。
B、dataNode: MyCAT的逻辑数据节点,是存放table的具体物理节点,也称之为分片节点,通过DataSource来关联到后端某个具体数据库上,一般来说,为了高可用性,每个DataNode都设置两个DataSource,一主一从,当主节点宕机,系统自动切换到从节点。
C、dataHost:定义某个物理库的访问地址,用于捆绑到dataNode上。
C.1、dataHost有两个参数需要注意:balance和 switchType
其中,balance指的负载均衡类型,目前的取值有4种:
1. balance="0", 不开启读写分离机制,所有读操作都发送到当前可用的writeHost上。
2. balance="1",全部的readHost与stand by writeHost参与select语句的负载均衡,简单的说,当双主双从模式(M1->S1,M2->S2,并且M1与 M2互为主备),正常情况下,M2,S1,S2都参与select语句的负载均衡。
3. balance="2",所有读操作都随机的在writeHost、readhost上分发。
4. balance="3",所有读请求随机的分发到wiriterHost对应的readhost执行,writerHost不负担读压力
switchType指的是切换的模式,目前的取值也有4种:
1. switchType='-1' 表示不自动切换
2. switchType='1' 默认值,表示自动切换
3. switchType='2' 基于MySQL主从同步的状态决定是否切换,心跳语句为 show slave status
4. switchType='3'基于MySQL galary cluster的切换机制(适合集群),心跳语句为 show status like 'wsrep%'。
因此,该配置文件中的balance="1"意味着作为stand by writeHost的hostS1和hostS2将参与select语句的负载均衡,这就实现了主从的读写分离,switchType='-1'意味着当主挂掉的时候,不进行自动切换,即hostS1和hostS2并不会被提升为主,仍只提供读的功能。这就避免了将数据读进slave的可能性,毕竟,单纯的MySQL主从集群并不允许将数据读进slave中,除非配置的是双master。
C.2、注意writeHost/readHost中的url,user,password的值均为上述基础设施中的Mysql的连接信息。

第二步、上面我们将数据源的关系全部配置完毕,既然我们需要通过MyCat访问最终的数据源,则需要在server.xml配置连接信息: 
<user name="root">
<property name="password">123456</property>
<property name="schemas">TESTDB</property>
</user>
参数说明:
name:用户名
password:密码
schemas:实例名,和schema.xml定义的schema对应,这里的实例名是虚拟名,也就是对mycat服务的一种别名,是 应用程序以及客户端连接的入口。

第三步、为了后续可以比较好的验证监控,我们需要将log级别调整为debug:
日志存放在logs/mycat.log中,每天一个文件,日志的配置是在conf/log4j.xml中,根据自己的需要,可以调整输出级别为debug,debug级别下,会输出更多的信息,方便排查问题。

第四步、启动服务,在Windows 下 运行:mycat.bat console在控制台启动程序,也可以装载成服务,若此程序运行有问题,也可以运行startup_nowrap.bat,确保java命令可以在命令执行,我们直接通过startup_nowrap.bat启动服务:

启动服务后默认数据端口为8066,管理端口为9066。
(通过如下命令可以安装为服务
安装mycat服务 :mycate install 
启动mycat服务 :mycate start
停止mycat服务 :mycate stop
注意:当修改配置文件后,需要重启mycat服务)

验证
1、首先需要连接上MyCat,我们进入任意一个MySQL打开客户端连接即可,通过mysql -uroot -p -h127.0.0.1 -P8066

也可以通过客户端工具连接


2、在登录时没有指定逻辑库,我们通过use TESTDB命令切换:


3、此时我们即可进行查询:

特别关注上述的红色部分,在Master中我们为111,由于我们是单向复制,故我将在3321中的数据做了点手脚

从而也证明了确实是从Slave库读取的数据,我们来看下日志呢
2017-02-05 13:53:21.139 DEBUG [$_NIOREACTOR-3-RW] (io.mycat.server.NonBlockingSession.releaseConnection(NonBlockingSession.java:341)) - release connection MySQLConnection [id=11, lastTime=1486274001132, user=root, schema=springboot1, old shema=springboot1, borrowed=true, fromSlaveDB=false, threadId=3033, charset=utf8, txIsolation=3, autocommit=true, attachment=dn1{SELECT * FROm t_sys_user r}, respHandler=SingleNodeHandler [node=dn1{SELECT * FROm t_sys_user r}, packetId=126], host=localhost, port=3321, statusSync=null, writeQueue=0, modifiedSQLExecuted=false]
此次正好从我们上述调整的3321服务中读取数据,也证明了为何读取的非111,而是1111,既然我们有两个从服务,也不会每次的读取都是1111结果,如下即从3322服务读取

2017-02-05 15:11:25.788 DEBUG [$_NIOREACTOR-1-RW] (io.mycat.server.NonBlockingSession.releaseConnection(NonBlockingSession.java:341)) - release connection MySQLConnection [id=16, lastTime=1486278685777, user=root, schema=springboot1, old shema=springboot1, borrowed=true, fromSlaveDB=true, threadId=15, charset=utf8, txIsolation=3, autocommit=true, attachment=dn1{SELECT * FROm t_sys_user r}, respHandler=SingleNodeHandler [node=dn1{SELECT * FROm t_sys_user r}, packetId=127], host=127.0.0.1, port=3322, statusSync=io.mycat.backend.mysql.nio.MySQLConnection$StatusSync@1bac8b63, writeQueue=0, modifiedSQLExecuted=false]
可以看到MyCat已经为我们很好的实现了负载均衡。

4、既然读取确实是我们期望的,那么写入呢,直接通过命令行新增一个数据行

通过对Master和2个Slave库的查询,均有新增数据,那么此次数据的插入是通过哪个服务呢,继续关注日志,
2017-02-05 14:09:03.447 DEBUG [$_NIOREACTOR-2-RW] (io.mycat.server.NonBlockingSession.releaseConnection(NonBlockingSession.java:341)) - release connection MySQLConnection [id=10, lastTime=1486274943433, user=root, schema=springboot1, old shema=springboot1, borrowed=true, fromSlaveDB=false, threadId=3087, charset=utf8, txIsolation=3, autocommit=true, attachment=dn1{INSERT INTO springboot1.t_sys_user ( password, `loginName`) VALUES ('12', '12')}, respHandler=SingleNodeHandler [node=dn1{INSERT INTO springboot1.t_sys_user ( password, `loginName`) VALUES ('12', '12')}, packetId=1], host=localhost, port=3310, statusSync=null, writeQueue=0, modifiedSQLExecuted=true]
可以看到红色部分,验证成功。

总结
通过MyCat实现读写分离将对我们的业务代码没有任何的侵入性,并且在多个从库的情况下实现了复杂均衡。当然MyCat的作用不止这么多,在特性中有很多的介绍,后续将慢慢展开。
0 0
原创粉丝点击