一 简介

 官方网站:http://www.mycat.org.cn/

 MyCat是一个开源的分布式数据库系统,是一个实现了MySQL协议的服务器,前端用户可以把它看作是一个数据库代理(类似于Mysql Proxy),用MySQL客户端工具和命令行访问,

  而其后端可以用MySQL原生协议与多个MySQL服务器通信,也可以用JDBC协议与大多数主流数据库服务器通信,其核心功能是分表分库,即将一个大表水平分割为N个小表,存储在后端MySQL服务器里或

  者其他数据库里

 

 应用场景:

  单纯的读写分离,此时配置最为简单,支持读写分离,主从切换;

  分表分库,对于超过1000万的表进行分片,最大支持1000亿的单表分片;

  多租户应用,每个应用一个库,但应用程序只连接Mycat,从而不改造程序本身,实现多租户化;

  报表系统,借助于Mycat的分表能力,处理大规模报表的统计;

  替代Hbase,分析大数据;

  作为海量数据实时查询的一种简单有效方案,比如100亿条频繁查询的记录需要在3秒内查询出来结果,除了基于主键的查询,还可能存在范围查询或其他属性查询,此时Mycat可能是最简单有效的选择

 

 不适合的应用场景:

  设计使用Mycat时有非分片字段查询,请慎重使用Mycat,可以考虑放弃!

  设计使用Mycat时有分页排序,请慎重使用Mycat,可以考虑放弃!

  设计使用Mycat时如果要进行表JOIN操作,要确保两个表的关联字段具有相同的数据分布,否则请慎重使用Mycat,可以考虑放弃!

  设计使用Mycat时如果有分布式事务,得先看是否得保证事务得强一致性,否则请慎重使用Mycat,可以考虑放弃!

 

 工作原理:

  Mycat的原理中最重要的一个动词是“拦截”,它拦截了用户发送过来的SQL语句,首先对SQL语句做了一些特定的分析:如分片分析、路由分析、读写分离分析、缓存分析等,然后将此SQL发往后端的真实数

    据库,并将返回的结果做适当的处理,最终再返回给用户

 

 分片策略:

  水平分片:一个表格的数据分割到多个节点上,按照行分隔。

  垂直分片:一个数据库中多个表格A,B,C,A存储到节点1上,B存储到节点2上,C存储到节点3上

  Mycat通过定义表的分片规则来实现分片,每个表格可以捆绑一个分片规则,每个分片规则指定一个分片字段并绑定一个函数,来实现动态分片算法

 

二 安装

  安装java环境(https://www.oracle.com/java/technologies/javase/javase-jdk8-downloads.html

[root@localhost ~]# tar xvf jdk-8u181-linux-x64.tar.gz
[root@localhost ~]# mv jdk1.8.0_181/ /usr/local/java
[root@localhost ~]# cat /etc/profile.d/java.sh 
export JAVA_HOME=/usr/local/java
export PATH=$JAVA_HOME/bin:$PATH
[root@localhost ~]# . /etc/profile.d/java.sh

  安装mycat

[root@localhost ~]# tar xvf Mycat-server-1.6-RELEASE-20161028204710-linux.tar.gz -C /usr/local/

 

三 配置文件

/usr/local/mycat/conf/server.xml  主要配置客户端如何连接mycat
1 [root@localhost ~]# cat /usr/local/mycat/conf/server.xml
  2 <?xml version="1.0" encoding="UTF-8"?>
  3 <!-- - - Licensed under the Apache License, Version 2.0 (the "License"); 
  4         - you may not use this file except in compliance with the License. - You 
  5         may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 
  6         - - Unless required by applicable law or agreed to in writing, software - 
  7         distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT 
  8         WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the 
  9         License for the specific language governing permissions and - limitations 
 10         under the License. -->
 11 <!DOCTYPE mycat:server SYSTEM "server.dtd">
 12 <mycat:server xmlns:mycat="http://io.mycat/">
 13         <system>
 14         <property name="useSqlStat">0</property>  <!-- 1为开启实时统计、0为关闭 -->
 15         <property name="useGlobleTableCheck">0</property>  <!-- 1为开启全加班一致性检测、0为关闭 -->
 16 
 17                 <property name="sequnceHandlerType">2</property>
 18       <!--  <property name="useCompression">1</property>--> <!--1为开启mysql压缩协议-->
 19         <!--  <property name="fakeMySQLVersion">5.6.20</property>--> <!--设置模拟的MySQL版本号-->
 20         <!-- <property name="processorBufferChunk">40960</property> -->
 21         <!-- 
 22         <property name="processors">1</property> 
 23         <property name="processorExecutor">32</property> 
 24          -->
 25                 <!--默认为type 0: DirectByteBufferPool | type 1 ByteBufferArena-->
 26                 <property name="processorBufferPoolType">0</property>
 27                 <!--默认是65535 64K 用于sql解析时最大文本长度 -->
 28                 <!--<property name="maxStringLiteralLength">65535</property>-->
 29                 <!--<property name="sequnceHandlerType">0</property>-->
 30                 <!--<property name="backSocketNoDelay">1</property>-->
 31                 <!--<property name="frontSocketNoDelay">1</property>-->
 32                 <!--<property name="processorExecutor">16</property>-->
 33                 <!--
 34                         <property name="serverPort">8066</property> <property name="managerPort">9066</property> 
 35                         <property name="idleTimeout">300000</property> <property name="bindIp">0.0.0.0</property> 
 36                         <property name="frontWriteQueueSize">4096</property> <property name="processors">32</property> -->
 37                 <!--分布式事务开关,0为不过滤分布式事务,1为过滤分布式事务(如果分布式事务内只涉及全局表,则不过滤),2为不过滤分布式事务,但是记录分布式事务日志-->
 38                 <property name="handleDistributedTransactions">0</property>
 39 
 40                         <!--
 41                         off heap for merge/order/group/limit      1开启   0关闭
 42                 -->
 43                 <property name="useOffHeapForMerge">1</property>
 44 
 45                <!--
 46                         单位为m
 47                 -->
 48                 <property name="memoryPageSize">1m</property>
 49 
 50                 <!--
 51                         单位为k
 52                 -->
 53                 <property name="spillsFileBufferSize">1k</property>
 54 
 55                 <property name="useStreamOutput">0</property>
 56 
 57                 <!--
 58                         单位为m
 59                 -->
 60                 <property name="systemReserveMemorySize">384m</property>
 61 
 62 
 63                 <!--是否采用zookeeper协调切换  -->
 64                 <property name="useZKSwitch">true</property>
 65 
 66 
 67         </system>
 68 
 69         <!-- 全局SQL防火墙设置 -->
 70         <!-- 
 71         <firewall> 
 72            <whitehost>
 73               <host host="127.0.0.1" user="mycat"/>
 74               <host host="127.0.0.2" user="mycat"/>
 75            </whitehost>
 76        <blacklist check="false">
 77        </blacklist>
 78         </firewall>
 79         -->
 80 
 81         <user name="root">                      #连接mycat的用户名
 82                 <property name="password">123456</property>   #密码
 83                 <property name="schemas">TESTDB</property>    #数据逻辑库,如果有多个逻辑库可使用","分开
 84 
 85                 <!-- 表级 DML 权限设置 -->
 86                 <!--            
 87                 <privileges check="false">
 88                         <schema name="TESTDB" dml="0110" >
 89                                 <table name="tb01" dml="0000"></table>
 90                                 <table name="tb02" dml="1111"></table>
 91                         </schema>
 92                 </privileges>           
 93                  -->
 94         </user>
 95 
 96         <user name="user">                      #这里配置的是一个只读用户,此用户不可进行写操作
 97                 <property name="password">user</property>
 98                 <property name="schemas">TESTDB</property>
 99                 <property name="readOnly">true</property>
100         </user>
101 
102 </mycat:server>

配置分库分表及读写分离

[root@localhost ~]# cat /usr/local/mycat/conf/schema.xml
<?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="travelrecord" dataNode="dn1,dn2,dn3" rule="auto-sharding-long" />
          <table name="company" primaryKey="ID" type="global" dataNode="dn1,dn2,dn3" />
          <table name="hotnews" primaryKey="ID" autoIncrement="true" dataNode="dn1,dn2,dn3"
                rule="mod-long" />
        </schema>
        <dataNode name="dn1" dataHost="localhost1" database="db1" />
        <dataHost name="localhost1" maxCon="1000" minCon="10" balance="0"
                          writeType="0" dbType="mysql" dbDriver="native" switchType="1"  slaveThreshold="100">
                <heartbeat>select user()</heartbeat>
                <!-- can have multi write hosts -->
                <writeHost host="hostM1" url="localhost:3306" user="root"
                                   password="123456">
                        <!-- can have multi read hosts -->
                        <readHost host="hostS2" url="192.168.1.200:3306" user="root" password="xxx" />
                </writeHost>
                <writeHost host="hostS1" url="localhost:3316" user="root"
                                   password="123456" />
          
          <writeHost host="hostS2" url="192.168.1.200:3306" user="root" password="xxx" />    #将从机配置成writeHost做切换
                <!-- <writeHost host="hostM2" url="localhost:3316" user="root" password="123456"/> -->
        </dataHost>

</mycat:schema>

  参数说明:

   schema:总标签, 包括虚拟库, 以及连接属性, 还有虚拟节点

    name:定义了虚拟库的名字,这个名字需要和server.xml定义一致

    dataNode:定义了虚拟节点名字,这个需要和下一级的dataNode标签里的name属性一致

   dataNode:标签,包括dataNode的名字,虚拟host属性,以及要使用后端物理机那个数据库

    name:定义dataNode的名字,该属性提供给schema里的dataNode使用,须一致

    dataHost:可自定义,下一级标签需要使用该信息

    database:指定使用后端物理机的那个数据库,就是把上级标签定义的虚拟数据库映射到后端物理机上的那个真实的数据库,该数据库在后端物理机上的Mysql是真实存在的

   table:表名,物理数据库中表名

    dataNode:表存储到哪些节点,多个节点用逗号分隔。节点为下文dataNode设置的name

    primaryKey:主键字段名,自动生成主键时需要设置

    autoIncrement:是否自增

    rule:分片规则名

   dataHost:标签,包括后端物理机的属性,地址,端口,以及用户名密码,还有该物理机是负责写还是读,等等

    name:使用上级标签也就是dataNode里的 dataHost的名字,这个必须保持一致

    balance:读负载均衡类型,目前的取值有 4 种:

     0 - 不开启读写分离机制,所有读操作都发送到当前可用的writeHost 上

     1 - 全部的 readHost 与 stand by writeHost 参与 select 语句的负载均衡

     2 - 所有读操作都随机的在 writeHost、 readhost 上分发

     3 - 所有读请求随机的分发到 wiriterHost 对应的 readhost 执行,writerHost 不负担读压力(注意 balance=3 只在 1.4 及其以后版本有, 1.3 没有)

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

     0 - 所有写操作发送到配置的第一个writeHost,第一个挂了切到备writeHost,重新启动后已切换后的为准,切换记录在配置文件中:dnindex.properties

     1 - 所有写操作都随机的发送到配置的 writeHost

     2 - 没实现

    switchType:切换类型

     -1 - 表示不自动切换

     1 - 默认值,自动切换

     2 - 基于MySQL主从同步的状态来决定是否切换。需修改heartbeat语句(即心跳语句):show slave status

     3 - 基于Mysql Galera Cluster(集群多节点复制)的切换机制。需修改heartbeat语句(即心跳语句):show status like 'wsrep%'

   writeHost,readHost:标签, 定义后端物理机属性,定义了该物理机是可读还是可写,可以有多个

     在一个dataHost内可以定义多个writeHost和readHost。但是,如果writeHost指定的后端数据库宕机,那么这个writeHost绑定的所有readHost都将不可用

     另一方面,由于这个writeHost宕机系统会自动的检测到,并切换到备用的writeHost上去

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

 

四 启动服务(默认端口:8066-工作端口 9066-管理端口)

/usr/local/mycat/bin/mycat start &

 

五 部署读写分离,分库分表,读写切换(实验可用不同数据进行验证)

 在所有mysql服务器上创建授权mycat登录并验证

grant all on *.* to mycat@192.168.198.134 identified by 'mycat';

 配置mycat(编写如上配置文件)

 启动服务,连接验证

mysql -umycat -pmycat -h 192.168.198.134 -P 8066

 客户端连接后进入到虚拟库查看表的内容,验证读负载均衡

 插入一些数据验证写操作

 关闭主写库验证写库切换

 

六 管理端口常用命令

mysql -uroot -p123456 -h 192.168.198.134 -P9066

show @@help;

列出所有管理命令

reload @@config;

更新 schema.xml 配置文件(不用重启)

reload @@config_all;

更新所有配置文件

show @@datanode;

查询显示 Mycat 数据节点列表

show @@version;

查看版本

show @@connection;

查看连接信息

show @@backend;

查看后端连接状态