Mycat部署(单库分表)

------理论部分摘自Mycat 权威指南,仅做入门参考-----

一、Mycat应用场景

Mycat 发展到现在,适用的场景已经很丰富,而且不断有新用户给出新的创新性的方案,以下是几个典型的 应用场景:

• 1、单纯的读写分离,此时配置最为简单,支持读写分离,主从切换;
• 2、分表分库,对于超过 1000 万的表进行分片,最大支持 1000 亿的单表分片;
• 3、多租户应用,每个应用一个库,但应用程序只连接 Mycat,从而不改造程序本身,实现多租户化;
• 4、报表系统,借助于 Mycat 的分表能力,处理大规模报表的统计;
• 5、替代 Hbase,分析大数据;
• 6、作为海量数据实时查询的一种简单有效方案,比如 100 亿条频繁查询的记录需要在 3 秒内查询出来结果,除了基于主键的查询,还可能存在范围查询或其他属性查询,此时 Mycat 可能是最简单有效的选择。

二、何为数据切分(分库分表)?

简单来说,就是指通过某种特定的条件,将我们存放在同一个数据库中的数据分散存放到多个数据库(主机) 上面,以达到分散单台设备负载的效果。
数据的切分(Sharding)根据其切分规则的类型,可以分为两种切分模式。
一种是按照不同的表(或者 Schema)来切分到不同的数据库(主机)之上,这种切可以称之为数据的垂直(纵向)切分;
另外一种则是根据 表中的数据的逻辑关系,将同一个表中的数据按照某种条件拆分到多台数据库(主机)上面,这种切分称之为数 据的水平(横向)切分。
垂直切分的最大特点就是规则简单,实施也更为方便,尤其适合各业务之间的耦合度非常低,相互影响很小, 业务逻辑非常清晰的系统。在这种系统中,可以很容易做到将不同业务模块所使用的表分拆到不同的数据库中。 根据不同的表来进行拆分,对应用程序的影响也更小,拆分规则也会比较简单清晰。
水平切分于垂直切分相比,相对来说稍微复杂一些。因为要将同一个表中的不同数据拆分到不同的数据库中, 对于应用程序来说,拆分规则本身就较根据表名来拆分更为复杂,后期的数据维护也会更为复杂一些。

数据切分的原则:
第一原则:能不切分尽量不要切分。
第二原则:如果要切分一定要选择合适的切分规则,提前规划好。 第三原则:数据切分尽量通过数据冗余或表分组(Table Group)来降低跨库 Join 的可能。 第四原则:由于数据库中间件对数据 Join 实现的优劣难以把握,而且实现高性能难度极大,业务读取尽量
少使用多表 Join。

三、Mycat 是什么?

Mycat 是数据库中间件,就是介于数据库与应用之间,进行数据处理与交互的中间服务。 由于前面讲的对数据进行分片处理之后,从原有的一个库,被切分为多个分片数据库,所有的分片数据库集群构 成了整个完整的数据库存储。
在这里插入图片描述
所以有了数据库中间件,应用只需要集中与业务处理,大量的通用的数据聚合,事务,数据源切换都由中间 件来处理,中间件的性能与处理能力将直接决定应用的读写性能,所以一款好的数据库中间件至关重要。、环境

四、环境准备

  1. JDK下载
    http://www.oracle.com/technetwork/java/javase/downloads/jdk7-downloads-1880260.html 注:必须 JDK7 或更高版本.
  2. MySQL下载
    https://dev.mysql.com/downloads/mysql/
    注:MyCAT 支持多种数据库接入,如:MySQL、SQLServer、Oracle、MongoDB 等,推荐使用MySQL 做集群。
  3. MyCAT 项目主页
    https://github.com/MyCATApache/
    注:MyCAT 相关源码、文档都可以在此地址下进行下载。

linux 下可以下载 Mycat-server-xxxxx.linux.tar.gz 解压在某个目录下,注意目录不能有空格,在Linux(Unix)下,建议放在 usr/local/Mycat 目录下,如下:
在这里插入图片描述

MyCAT 目前主要通过配置文件的方式来定义逻辑库和相关配置:

MYCAT_HOME/conf/schema.xml 中定义逻辑库,表、分片节点等内容;
MYCAT_HOME/conf/rule.xml 中定义分片规则;
MYCAT_HOME/conf/server.xml 中定义用户以及系统相关变量,如端口等。

建议大家选择 1.6.5 版本,毕竟是比较稳定的版本,且 1.6.5 版本 才开始支持单库分表。

1. 修改 server.xml
shift+G 翻到文档末尾,找到以下一段,修改
#特别说明:
#user name及password不用于连接数据库,而是连接mycat 8066管理端口,无需在数据库中创建此用户,可以随意指定
#property name=“schemas” 的value值是自定义的逻辑库名称,不一定是真实的数据库schema name,但是需要与schema.xml中的schema name一致

<!-- mycat的8066 端口连接的用户名,密码,逻辑数据库名 -->
 <user name="mycatu1" defaultAccount="true">
                <property name="password">123456</property>
                <property name="schemas">mydb</property>
                <privileges check="true">
                        <schema name="mydb" dml="0110" >
                                <table name="sbtest11" dml="1111"></table> 
                        </schema>
                </privileges>
        </user>

2.修改schema.xml
schema 标签用于定义 MyCat 实例中的逻辑库,MyCat 可以有多个逻辑库,每个逻辑库都有自己的相关配 置。可以使用 schema 标签来划分这些不同的逻辑库。
如果不配置 schema 标签,所有的表配置,会属于同一个默认的逻辑库。

$ cat ../conf/schema.xml       
<?xml version="1.0"?>
<!DOCTYPE mycat:schema SYSTEM "schema.dtd">
<mycat:schema xmlns:mycat="http://io.mycat/">
		<!--  "mydb"逻辑库名-->
        <schema name="mydb" checkSQLschema="false" sqlMaxLimit="100">
                <!-- name: 表名,分表主键,子表,数据节点,分表规则 -->                                                  
                <table name="sbtest11" primaryKey="id" autoIncrement="true" subTables="sbtest11_$1-3" dataNode="dn1" rule="mod-long" />    
        </schema>
        <!--       database="test”是实际的数据库名称    -->
        <dataNode name="dn1" dataHost="localhost1" database="test"/>
        <dataHost name="localhost1" maxCon="1000" minCon="10" balance="3"
                          writeType="0" dbType="mysql" dbDriver="native" switchType="1"  slaveThreshold="100">
                <heartbeat>select user()</heartbeat>
                <!-- can have multi write hosts -->
                <writeHost host="hostM1" url="192.168.0.156:6001" user="root" password="123456">
                        <!-- can have multi read hosts -->
                        <readHost host="hostS1" url="192.168.0.156:6001" user="root" password="123456" />

                </writeHost>
        </dataHost>
</mycat:schema>

schema name 要和server.xml对应上,
user表设置分表3张 (sbtest11_1, sbtest11_2, sbtest11_3),只设置一个 datanote(即一个物理数据库服务),
rule采用取模模式mod-long。
writeHost 和 readHost设为同一数据库。

balance 属性
负载均衡类型,目前的取值有 3 种:
> balance="0", 不开启读写分离机制,所有读操作都发送到当前可用的 writeHost 上。
> balance="1",全部的 readHost 与 stand by writeHost 参与 select 语句的负载均衡,简单的说,当双主双从模式(M1->S1,M2->S2,并且 M1 与 M2 互为主备),正常情况下,M2,S1,S2 都参与 select 语句的负载 均衡。
> balance="2",所有读操作都随机的在 writeHost、readhost 上分发。
> balance="3",所有读请求随机的分发到 wiriterHost 对应的 readhost 执行,writerHost 不负担读压力,
注意 balance=3 只在 1.4 及其以后版本有,1.3 没有。

writeType 属性
负载均衡类型,目前的取值有 3 种:
> writeType="0", 所有写操作发送到配置的第一个 writeHost,第一个挂了切到还生存的第二个 writeHost, 重新启动后已切换后的为准,切换记录在配置文件中:dnindex.properties .
> writeType="1",所有写操作都随机的发送到配置的 writeHost,1.5 以后废弃不推荐。

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

3.修改 rule.xml

#cp rule.xml{,.bak}
#cat /dev/null>rule.xml
vi rule.xml 

#添加如下内容
#Mycat分片(分库分表)规则, rule.xml文件中默认有全部的分库分表规则,保留需要的即可

$ cat ../conf/rule.xml        
<?xml version="1.0" encoding="UTF-8"?>
<!-- - - Licensed under the Apache License, Version 2.0 (the "License"); 
        - you may not use this file except in compliance with the License. - You 
        may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 
        - - Unless required by applicable law or agreed to in writing, software - 
        distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT 
        WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the 
        License for the specific language governing permissions and - limitations 
        under the License. -->
<!DOCTYPE mycat:rule SYSTEM "rule.dtd">
<mycat:rule xmlns:mycat="http://io.mycat/">
        <tableRule name="mod-long">
                <rule>
                        <columns>id</columns>
                        <algorithm>mod-long</algorithm>
                </rule>
        </tableRule>
        <function name="mod-long" class="io.mycat.route.function.PartitionByMod">
                <!-- how many data nodes -->
                <property name="count">3</property>
        </function>

</mycat:rule>

此次选用默认的mod-long规则,只需修改count数.
修改property count 等于3(默认值即为3,如果你需要分出更多的表,在此进行修改为你的分表数)。

这样,配置就已经完成了。

四、物理数据库构建
先在MySQL库上,建数据库test,并在此数据库中建4张表,sbtest11、sbtest11_$1-3,且四张表结构相同。

CREATE TABLE `sbtest11` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `k` int(11) NOT NULL DEFAULT '0',
  `c` char(120) NOT NULL DEFAULT '',
  `pad` char(60) NOT NULL DEFAULT '',
  PRIMARY KEY (`id`),
  KEY `k_1` (`k`),
  KEY `index_c` (`c`)

create table sbtest11_1 like sbtest11;
create table sbtest11_2 like sbtest11;
create table sbtest11_3 like sbtest11;

五、启动Mycat

MyCAT 在 Linux 中部署启动时,首先需要在 Linux 系统的环境变量中配置 MYCAT_HOME,操作方式如下:

  1. vi /etc/profile,在系统环境变量文件中增加
$ cd  /usr/local
$ ln -s  /opt/module/mycat Mycat     
echo  'export MYCAT_HOME=/usr/local/Mycat'>>/etc/profile
  1. 执行 source /etc/profile 命令,使环境变量生效。
source /etc/profile 

如果是在多台 Linux 系统中组建的 MyCAT 集群,那需要在 MyCAT Server 所在的服务器上配置对其他 ip 和主机名的映射,配置方式如下: vi /etc/hosts
例如:我有 4 台机器,配置如下:
IP 主机名:
192.168.100.2 sam_server_1
192.168.100.3 sam_server_2
192.168.100.4 sam_server_3
192.168.100.5 sam_server_4

编辑完后,保存文件。

进入mycat/bin 目录
启动|停止|重启|查看状态:

./mycat start | stop | restart | status

查看logs/下的wrapper.log和mycat.log可以查看运行时问题和异常。
mycat启动日志:

cat ./logs/wrapper.log

mycat 应用日志:

cat ./logs/mycat.log

六、测试
连接mycat, 端口:8066,账号:mycatu1, 密码:123456
使用你在 server.xml文件中配置的用户名和密码
执行sql语句,查看执行过程。
连接进8066,展示的数据库和数据库表都是schema中配置的逻辑库和表

$ mysql -h 192.168.0.156 -P8066 -umycatu1 -p123456
>show databases;
+----------+
| DATABASE |
+----------+
| mydb     |
+----------+
1 row in set (0.01 sec)
>show tables;
+----------------+
| Tables in mydb |
+----------------+
| sbtest11       |
+----------------+
1 row in set (0.00 sec)

#8066测试插入数据
(mycatu1@192.168.0.156:mydb09:06:44)>insert into sbtest11(id,k,c,pad) values(1,1,'2','3');    
(mycatu1@192.168.0.156:mydb09:08:40)>insert into sbtest11(id,k,c,pad) values(2,1,'2','92467260075-29317133430-40030751771-62719549546-51313121034');    
(mycatu1@192.168.0.156:mydb09:08:55)>insert into sbtest11(id,k,c,pad) values(3,1,'2','92467260075-29317133430-40030751771-62719549546-51313121034'); 

(mycatu1@192.168.0.156:mydb09:30:20)>select * from sbtest11;
+----+---+---+-------------------------------------------------------------+
| id | k | c | pad                                                         |
+----+---+---+-------------------------------------------------------------+
|  3 | 1 | 2 | 92467260075-29317133430-40030751771-62719549546-51313121034 |
|  1 | 1 | 2 | 3                                                           |
|  2 | 1 | 2 | 92467260075-29317133430-40030751771-62719549546-51313121034 |
+----+---+---+-------------------------------------------------------------+
3 rows in set (0.18 sec)

#回到test库查看效果
(root@localhost:test09:09:28)>select * from sbtest11;
Empty set (0.00 sec)

(root@localhost:test09:09:46)>select * from sbtest11_1;
+----+---+---+-------------------------------------------------------------+
| id | k | c | pad                                                         |
+----+---+---+-------------------------------------------------------------+
|  3 | 1 | 2 | 92467260075-29317133430-40030751771-62719549546-51313121034 |
+----+---+---+-------------------------------------------------------------+
1 row in set (0.00 sec)

(root@localhost:test09:09:51)>select * from sbtest11_2;
+----+---+---+-----+
| id | k | c | pad |
+----+---+---+-----+
|  1 | 1 | 2 | 3   |
+----+---+---+-----+
1 row in set (0.00 sec)

(root@localhost:test09:09:54)>select * from sbtest11_3;
+----+---+---+-------------------------------------------------------------+
| id | k | c | pad                                                         |
+----+---+---+-------------------------------------------------------------+
|  2 | 1 | 2 | 92467260075-29317133430-40030751771-62719549546-51313121034 |
+----+---+---+-------------------------------------------------------------+
1 row in set (0.00 sec)

七、debug模式下解析SQL的执行
修改日志记录级别为debug: vi $MYCAT_HOME/conf/log4j2.xml
将默认的info级别调整成debug级别

<asyncRoot level="debug" includeLocation="true">

#连接到8066端口,执行

select * from sbtest11

#$MYCAT_HOME/logs/mycat.log输出

#命令行接收到指令

2019-11-11 21:52:06.402 DEBUG [$_NIOREACTOR-0-RW] (io.mycat.net.FrontendConnection.query(FrontendConnection.java:340)) - ServerConnection [id=1, schema=mydb, host=192.168.0.156, user=mycatu1,txIsolation=3, autocommit=true, schema=mydb, executeSql=show tables] select * from sbtest11
2019-11-11 21:52:06.457 DEBUG [$_NIOREACTOR-0-RW] (io.mycat.server.ServerQueryHandler.query(ServerQueryHandler.java:57)) - ServerConnection [id=1, schema=mydb, host=192.168.0.156, user=mycatu1,txIsolation=3, autocommit=true, schema=mydb, executeSql=select * from sbtest11]select * from sbtest11
2019-11-11 21:52:06.462 DEBUG [$_NIOREACTOR-0-RW] (io.mycat.cache.impl.EnchachePool.get(EnchachePool.java:77)) - SQLRouteCache  miss cache ,key:mydbselect * from sbtest11

####由于只配置了一个dn1,而且数据只有在dn1上才有,可以看出sql只被路由到dn1执行

2019-11-11 21:52:06.530 DEBUG [$_NIOREACTOR-0-RW] (io.mycat.cache.impl.EnchachePool.putIfAbsent(EnchachePool.java:60)) - SQLRouteCache add cache ,key:mydbselect * from sbtest11 value:select * from sbtest11, route={
   1 -> dn1{SELECT *
FROM sbtest11_1
LIMIT 100}
   2 -> dn1{SELECT *
FROM sbtest11_2
LIMIT 100}
   3 -> dn1{SELECT *
FROM sbtest11_3
LIMIT 100}
}
2019-11-11 21:52:06.530 DEBUG [$_NIOREACTOR-0-RW] (io.mycat.server.NonBlockingSession.execute(NonBlockingSession.java:126)) - ServerConnection [id=1, schema=mydb, host=192.168.0.156, user=mycatu1,txIsolation=3, autocommit=true, schema=mydb, executeSql=select * from sbtest11]select * from sbtest11, route={
   1 -> dn1{SELECT *
FROM sbtest11_1
LIMIT 100}
   2 -> dn1{SELECT *
FROM sbtest11_2
LIMIT 100}
   3 -> dn1{SELECT *
FROM sbtest11_3
LIMIT 100}
} rrs 
2019-11-11 21:52:06.539 DEBUG [$_NIOREACTOR-0-RW] (io.mycat.backend.mysql.nio.handler.MultiNodeQueryHandler.<init>(MultiNodeQueryHandler.java:128)) - execute mutinode query select * from sbtest11
2019-11-11 21:52:06.541 DEBUG [$_NIOREACTOR-0-RW] (io.mycat.backend.mysql.nio.handler.MultiNodeQueryHandler.<init>(MultiNodeQueryHandler.java:164)) - has data merge logic 
MySQLConnection [id=14, lastTime=1573480326535, user=root, schema=test, old shema=test, borrowed=true, fromSlaveDB=true, threadId=4292, charset=utf8, txIsolation=3, autocommit=true, attachment=dn1{SELECT *
FROM sbtest11_1
LIMIT 100}, respHandler=io.mycat.backend.mysql.nio.handler.MultiNodeQueryHandler@ec29b0b, host=192.168.0.156, port=6001, statusSync=io.mycat.backend.mysql.nio.MySQLConnection$StatusSync@2c5da9ac, writeQueue=0, modifiedSQLExecuted=false]  false  3
... ...
####到这里,已经按照路由规则转给后边真正的数据库执行sql了

2019-11-11 21:52:06.559 DEBUG [$_NIOREACTOR-0-RW] (io.mycat.server.NonBlockingSession.releaseConnection(NonBlockingSession.java:386)) - release connection MySQLConnection [id=14, lastTime=1573480326535, user=root, schema=test, old shema=test, borrowed=true, fromSlaveDB=true, threadId=4292, charset=utf8, txIsolation=3, autocommit=true, attachment=dn1{SELECT *
FROM sbtest11_1
LIMIT 100}, respHandler=io.mycat.backend.mysql.nio.handler.MultiNodeQueryHandler@ec29b0b, host=192.168.0.156, port=6001, statusSync=io.mycat.backend.mysql.nio.MySQLConnection$StatusSync@2c5da9ac, writeQueue=0, modifiedSQLExecuted=false]
2019-11-11 21:52:06.559 DEBUG [$_NIOREACTOR-0-RW] (io.mycat.backend.datasource.PhysicalDatasource.releaseChannel(PhysicalDatasource.java:633)) - release channel MySQLConnection [id=14, lastTime=1573480326535, user=root, schema=test, old shema=test, borrowed=true, fromSlaveDB=true, threadId=4292, charset=utf8, txIsolation=3, autocommit=true, attachment=null, respHandler=null, host=192.168.0.156, port=6001, statusSync=null, writeQueue=0, modifiedSQLExecuted=false]
2019-11-11 21:52:06.571 DEBUG [$_NIOREACTOR-0-RW] (io.mycat.backend.mysql.nio.handler.MultiNodeQueryHandler.okResponse(MultiNodeQueryHandler.java:285)) - received ok response ,executeResponse:false from MySQLConnection [id=13, lastTime=1573480326551, user=root, schema=test, old shema=test, borrowed=true, fromSlaveDB=true, threadId=4291, charset=utf8, txIsolation=3, autocommit=true, attachment=dn1{SELECT *
FROM sbtest11_3
LIMIT 100}, respHandler=io.mycat.backend.mysql.nio.handler.MultiNodeQueryHandler@ec29b0b, host=192.168.0.156, port=6001, statusSync=io.mycat.backend.mysql.nio.MySQLConnection$StatusSync@45b85ea1, writeQueue=0, modifiedSQLExecuted=false]

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值