使用Mycat实现数据库读写分离

本文作者:蓝雄威,叩丁狼高级讲师。原创文章,转载请注明出处。

01前言

在上一篇文章中,我们基于CentOS7实现了MySQL的主从复制,我们需要把DML操作放在MySQL的主节点执行,需要把DQL操作放在MySQL的从节点执行.那在应用程序中我们怎么控制这个逻辑呢?
下面是一种可行的方案:
1.在项目中配置两个数据源(一主一从),分别是A(主)和B(从)。
2.在程序中判断是不是select操作,如果是就把数据源更换成B,如果不是select操作就更换成A,这样就可以实现程序中的读写分离了.
3.关于步骤2的更换数据源,Spring中是提供了AbstarctRoutingDataSource这个类在程序中实现数据源的切换的.
这种方案可行是可行,但是在应用程序端需要写挺多代码的,而且这些属于非业务层面的东西,写在项目中对项目来说是代码侵入了.
所以对于读写分离我们可以使用Mycat数据库中间件来完成.

02MyCat介绍

关于MyCat的详细简介,同学们可以去Mycat官网.下载Mycat权威指南.pdf来看,文章中的前世今生写得幽默有趣,挺有意思的,从描述来看都感觉看的不是本技术书,而是本小说哈.在这里我简单的介绍一下Mycat:

2008年阿里开源了一款数据库中间件Amoeba,随着业务的增长,这块产品不能支持目前已有的业务.阿里又开源了Cobar这款中间件,这款产品在阿里内部得到了很广泛的应用.(应用在了3000多台服务器,每天超过10亿次的数据库访问),当时一开源就得到了开发者和运维人员的追捧. 开源之后,阿里就没有对这款产品维护了,这款产品在生产环境中还是存在挺多问题的.在这样的场景下MyCat诞生了,2013年MyCat社区在Cobar的基础上进行了很大的改造和升级.

03Mycat优势

优势这个我就从官网上给同学们摘抄下来了:

基于阿里开源的Cobar产品而研发,Cobar的稳定性、可靠性、优秀的架构和性能以及众多成熟的使用案例使得MYCAT一开始就拥有一个很好的起点,站在巨人的肩膀上,我们能看到更远。业界优秀的开源项目和创新思路被广泛融入到MYCAT的基因中,使得MYCAT在很多方面都领先于目前其他一些同类的开源项目,甚至超越某些商业产品。

MYCAT背后有一支强大的技术团队,其参与者都是5年以上软件工程师、架构师、DBA等,优秀的技术团队保证了MYCAT的产品质量。

MYCAT并不依托于任何一个商业公司,因此不像某些开源项目,将一些重要的特性封闭在其商业产品中,使得开源项目成了一个摆设。

目前也有挺多公司在生产环境上使用Mycat的,使用案例,所以来说还是一款很不错,很稳定的产品.

04主要作用

主要作为分布式数据库系统的中间层
1.可以实现数据库的读写分离
2.支持负载均衡
3.支持后端MySQL高可用
4.数据库的垂直拆分
5.数据库水平拆分
关于Mycat如何实现数据库的分库分表,我在之前的简书中已经写了案例,数据库中间件Mycat+SpringBoot完成分库分表.

05Mycat的基本概念

Mycat概念

从上图可以看到,我们应用程序不是直接连接真实数据库的的,而是连接Mycat的.所以在Mycat的配置文件中我们就需要去定义逻辑库逻辑表真实库真实表的映射关系

06安装JDK环境变量

0.我们Mycat的安装是基于CentOS7环境来安装的,所以同学们先把基础环境搭建好哈.
1.Mycat是基于Java开发的一款中间件产品,所以要使用Mycat前需要把JDK的环境装上.JDK1.8安装包.
2.下载好jdk1.8安装包后,通过工具上传到服务器上.我们通常会把文件上传到/usr/local/software目录下

image

3.然后使用解压命令解压到/usr/local目录下

tar -zxvf jdk-8u161-linux-x64.tar.gz -C /usr/local
image

但是名字有些长,不方便我们设置环境变量,所以我们可以对这个文件夹重命名

mv jdk1.8.0_161/ jdk1.8
image

4.jdk解压好之后,我们就可以来配置环境变量了.

vi /etc/profile

编辑界面如下:


image

需要在这个文件中添加这两行配置:

export JAVA_HOME=/usr/local/jdk1.8
export PATH=.:$JAVA_HOME/bin:$PATH

编辑后如下图所示:


image

然后保存退出即可.
然后需要通过这个命令来重新加载配置文件:

source /etc/profile

设置好之后,通过这个命令查看环境变量是否配置好了.

java -version

如果看到下面这个内容,说明已经配置好了.


image.png

07安装Mycat

我们这次使用的是Mycat-server-1.6.7版本,下载好之后上传到服务器上.

image

然后使用命令进行解压

tar -zxvf Mycat-server-1.6.7.1-release-20190627191042-linux.tar.gz -C /usr/local/
image

这样我们就已经装好Mycat了,下一步就需要去配置Mycat的配置文件了.

08配置读写分离

我们可以先看看Mycat的文件目录结构

image

bin目录:存放Mycat运行的脚本
conf目录:存放Mycat的配置文件
logs目录:存放Mycat启动及运行的日志文件
我们现在需要进入到conf目录,修改配置文件.
image

目前来说,我们只需要关心server.xmlschema.xmlrule.xml这三个文件.
server.xml:主要配置Mycat的启动参数,连接密码,白名单,黑名单,访问权限控制等参数,我们暂时不修改,用默认的就可以了.
schema.xml:主要配置逻辑库、逻辑表和真实库、真实表之间的映射关系.
rule.xml:主要配置分库分表时的分片规则,此次试验中我们并不需要修改到.
目前我们的环境是这样的:

主机IP 角色
192.168.142.128 MySQL主节点
192.168.142.129 MySQL从节点
192.168.142.130 MyCat服务器

然后我们需要修改schema.xml文件,修改内容如下(建议直接复制我的,然后把Ip换一下就好了.):

<?xml version="1.0"?>
<!DOCTYPE mycat:schema SYSTEM "schema.dtd">
<mycat:schema xmlns:mycat="http://io.mycat/">
    <schema name="TESTDB" checkSQLschema="false" sqlMaxLimit="100">
    <table name="t_order" dataNode="dn01"/> 
    </schema>
    <dataNode name="dn01" dataHost="dh01" database="hello" />  
    <dataHost name="dh01" maxCon="1000" minCon="10" balance="1" writeType="0" dbType="mysql" dbDriver="native">  
            <heartbeat>select user()</heartbeat>  
            <writeHost host="192.168.142.128" url="192.168.142.128:3306" user="root" password="WolfCode_2017">
                <readHost host="192.168.142.129" url="192.168.142.129:3306" user="root" password="WolfCode_2017"></readHost>
            </writeHost>
            <writeHost host="192.168.142.129" url="192.168.142.129:3306" user="root" password="WolfCode_2017"></writeHost>
    </dataHost> 
</mycat:schema>

一、schema 解释

<schema name="TESTDB" checkSQLschema="false" sqlMaxLimit="100">

name属性:表示的是逻辑库的名字,是应用程序连接的时候的数据库名称.
checkSQLschema属性:当该值设置为 true 时,如果我们执行语句select * from TESTDB.travelrecord;则 MyCat 会把语句修改
select * from travelrecord;。即把表示 schema 的字符去掉,避免发送到后端数据库执行时报(ERROR
1146 (42S02): Table ‘testdb.travelrecord’ doesn’t exist)。

不过,即使设置该值为 true ,如果语句所带的是并非是 schema 指定的名字,例如:select * from
db1.travelrecord;
那么 MyCat 并不会删除 db1 这个字段,如果没有定义该库的话则会报错,所以在提供 SQL
语句的最好是不带这个字段。

sqlMaxLimit属性:当该值设置为某个数值时。每条执行的 SQL 语句,如果没有加上 limit 语句,MyCat 也会自动的加上所对应
的值。例如设置值为 100,执行select * from TESTDB.travelrecord;的效果为和执行select * from
TESTDB.travelrecord limit 100;
相同。
设置该值的话,MyCat 默认会把查询到的信息全部都展示出来,造成过多的输出。所以,在正常使用中,还
是建议加上一个值,用于减少过多的数据返回。
当然 SQL 语句中也显式的指定 limit 的大小,不受该属性的约束。
需要注意的是,如果运行的 schema 为非拆分库的,那么该属性不会生效。需要手动添加 limit 语句

二、table标签解释

<table name="t_order" dataNode="dn01"/>
Table 标签定义了 MyCat 中的逻辑表,所有需要拆分的表都需要在这个标签中定义。
name 属性:定义逻辑表的表名,这个名字就如同我在数据库中执行 create table 命令指定的名字一样,同个 schema 标
签中定义的名字必须唯一。
dataNode属性:定义这个逻辑表所属的 dataNode, 该属性的值需要和后面 dataNode 标签中 name 属性的值相互对应。

三、dataNode标签解释

<dataNode name="dn01" dataHost="dh01" database="hello" />
dataNode 标签定义了 MyCat 中的数据节点,也就是我们通常说所的数据分片。一个 dataNode 标签就是一个独立的数据分片。
name 属性:定义数据节点的名字,这个名字需要是唯一的,我们需要在 table 标签上应用这个名字,来建立表与分片对
应的关系。
dataHost 属性:该属性用于定义该分片属于哪个数据库实例的,属性值是引用 dataHost 标签上定义的 name 属性。
database 属性:该属性用于定义该分片属性哪个具体数据库实例上的具体库,因为这里使用两个纬度来定义分片,就是:实例+具体的库。因为每个库上建立的表和表结构是一样的。所以这样做就可以轻松的对表进行水平拆分。

四、dataHost标签解释

<dataHost name="dh01" maxCon="1000" minCon="10" balance="1" writeType="0" dbType="mysql" dbDriver="native">
作为 Schema.xml 中最后的一个标签,该标签在 mycat 逻辑库中也是作为最底层的标签存在,直接定义了具
体的数据库实例、读写分离配置和心跳语句。
name 属性:唯一标识 dataHost 标签,供上层的标签使用
maxCon 属性:指定每个读写实例连接池的最大连接。也就是说,标签内嵌套的 writeHost、readHost 标签都会使用这个属
性的值来实例化出连接池的最大连接数
minCon 属性:指定每个读写实例连接池的最小连接,初始化连接池的大小
balance 属性:
负载均衡类型,目前的取值有 3 种:

  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 不负担读压力,
    注意 balance=3 只在 1.4 及其以后版本有,1.3 没有。

writeType 属性:
负载均衡类型,目前的取值有 3 种:

  1. writeType="0", 所有写操作发送到配置的第一个 writeHost,第一个挂了切到还生存的第二个 writeHost,
    重新启动后已切换后的为准,切换记录在配置文件中:dnindex.properties .

2.writeType="1",所有写操作都随机的发送到配置的 writeHost,1.5 以后废弃不推荐。switchType 属

  • -1 表示不自动切换。
  • 1 默认值,自动切换。
  • 2 基于 MySQL 主从同步的状态决定是否切换。

dbType 属性:指定后端连接的数据库类型,目前支持二进制的 mysql 协议,还有其他使用 JDBC 连接的数据库。例如:
mongodb、oracle、spark 等。
dbDriver 属性:指定连接后端数据库使用的 Driver,目前可选的值有 native 和 JDBC。使用 native 的话,因为这个值执行的
是二进制的 mysql 协议,所以可以使用 mysql 和 maridb。其他类型的数据库则需要使用 JDBC 驱动来支持。
从 1.6 版本开始支持 postgresql 的 native 原始协议。
如果使用 JDBC 的话需要将符合 JDBC 4 标准的驱动 JAR 包放到 MYCAT\lib 目录下,并检查驱动 JAR 包中
包括如下目录结构的文件:META-INF\services\java.sql.Driver。在这个文件内写上具体的 Driver 类名,例如:
com.mysql.jdbc.Driver。

五、heartbeat标签解释

<heartbeat>select user()</heartbeat>
这个标签内指明用于和后端数据库进行心跳检查的语句。例如,MYSQL 可以使用 select user(),Oracle 可以
使用 select 1 from dual 等。

六、writeHost 标签、readHost 标签解释

这两个标签都指定后端数据库的相关配置给 mycat,用于实例化后端连接池。唯一不同的是,writeHost 指定写实例、readHost 指定读实例,组着这些读写实例来满足系统的要求。在一个 dataHost 内可以定义多个 writeHost 和 readHost。但是,如果 writeHost 指定的后端数据库宕机,那么这个 writeHost 绑定的所有 readHost 都将不可用。另一方面,由于这个 writeHost 宕机系统会自动的检测到,并切换到备用的 writeHost 上去。
host 属性:用于标识不同实例,一般 writeHost 我们使用M1,readHost 我们用S1。
url 属性:后端实例连接地址,如果是使用 native 的 dbDriver,则一般为 address:port 这种形式。用 JDBC 或其他的
dbDriver,则需要特殊指定。当使用 JDBC 时则可以这么写jdbc:mysql://localhost:3306/
user 属性:后端存储实例需要的用户名字。
password 属性:后端存储实例需要的密码。

08启动Mycat

使用命令

/usr/local/mycat/bin/mycat start

然后观察wrapper.log文件看是否已经启动成功.

image

出现这样的界面说明已经启动成功.可以通过Navicat客户端连接Mycat,或者通过应用程序连接也是可以的.


image

如果需要修改默认端口或者默认密码的话需要修改server.xml文件.在应用程序中连接的时候,和之前连接MySQL一样的.只是URL地址不一样而已,代码还是一样的.

09其他

目前我们连接Mycat之后,所有的读操作都是走从节点的,如果有需求需要读走主节点的话,可以使用Mycat中的注解,强制让读操作走主节点.

/*#mycat:db_type=master*/ 真实SQL
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 205,386评论 6 479
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,939评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,851评论 0 341
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,953评论 1 278
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,971评论 5 369
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,784评论 1 283
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,126评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,765评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,148评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,744评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,858评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,479评论 4 322
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,080评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,053评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,278评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,245评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,590评论 2 343

推荐阅读更多精彩内容