MyCAT

 ·  ☕ 10  · 👀...

介绍

同类产品:

  • OneProxy
  • MaxScale

基本概念

逻辑库

  • 对应用来说相当于MySQL中的数据库
  • 逻辑库可对应后端多个物理数据库
  • 逻辑库中并不保存数据

逻辑表

  • 对应用来说相当于MySQL中的数据表
  • 逻辑表可对应后端多个物理数据库中的表
  • 逻辑表中并不保存数据

逻辑表的类别

  • 分片表与非分片表是按是否被分片划分
  • 全局表:在所有分片中都存在的表(通常是一些字典表)
  • ER关系表:按ER关系进行分片的表

SQL拦截

  • 监控记录数据库写入操作
  • SQL审计

SQL防火墙

  • 统一控制哪些用户可以通过哪些主机访问后端数据库
  • 统一屏蔽一些SQL语句,加强安全控制

常见问题

MySQL的限制

对SQL语句的限制

  • create table like xxx / create table select xxx
  • 跨库多表关联查询、子查询
    可以使用使用全局表或ER分区表来解决
  • select for update / select lock in share mode
  • select into outfile/into var_name
  • 多表UPDATE或是UPDATE分片键
  • 跨分片update/delete [order by] limit

对事务支持的限制

  • MyCAT只支持弱分布式事务
  • 如事务commit后某节点失效则无法保证事务的一致性

MyCAT不适合的场景

  • 得不到支持的SQL的场景
  • 需要跨分片关联查询的场景
  • 需要保证跨分片事务强一致性的场景

解决跨分片关联的方式

  • 使用MyCAT全局表
  • 冗余部分关键数据
  • 使用API的方式获取数据

分片原则

  • 能不切分尽量不要切分
  • 选择合适的切分规则和分片键
  • 尽量避免跨分片JOIN操作

如何选择分片键

  • 尽可能的比较均匀分布数据到各个节点上
  • 该业务字段是最频繁的或者最重要的查询条件

订单表水平切分方案

  • 以customer_id作为分片键
  • 采用简单取模分片算法

架构图

基本使用

基本使用.png

异构数据库

异构数据库支持.png

读写分离及负载均衡

读写分离&负载均衡.png

业务数据库垂直切分

垂直切分.png

业务数据库水平切分

水平切分.png

MyCAT高可用

高可用.png

配置MyCAT

常用配置文件

配置文件 说明
server.xml 配置系统参数、用户权限、SQL防火墙及SQL拦截功能
schema.xml 配置逻辑库、逻辑表
rule.xml 配置水平分片的分片规则、分片规则所对应的分片函数
log4j2.xml 配置输出日志的格式、级别

server.xml配置参数

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
<!-- 配置Mycat环境参数 -->
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE mycat:server SYSTEM "server.dtd">
<mycat:server xmlns:mycat="http://org.opencloudb/">
   <system>
      <property name="defaultSqlParser">druidparser</property>
      <!-- 配置启动端口 -->
      <property name="serverPort">8066</property>
      <!-- 配置SQL拦截器  开始 -->
      <!-- 注意类路径不同版本的MyCAT是不一样的 -->
      <property name="sqlInterceptor">org.opencloudb.interceptor.impl.StatisticsSqlInterceptor</property>
      <!-- 配置拦截 sql 类型 -->
      <property name="sqlInterceptorType">select,update,insert,delete</property> 
      <!-- 配置sql 保存文件路径 -->
      <property name="sqlInterceptorFile">E:/mycat/sql.txt</property>
      <!-- 配置SQL拦截器  结束 -->

      <!-- 配置SQL防火墙  开始 -->
      <firewall>
        <!-- 配置ip白名单(用户对应的可以访问的ip地址) -->
        <whitehost> 
            <host user="mycat" host="127.0.0.1"></host>
        </whitehost> 
        
        <!-- 配置黑名单允许的 -->
        <blacklist check="true"> 
            <property name="selelctAllow">false</property>
        </blacklist> 
      </firewall>
      <!-- 配置SQL防火墙  开始 -->

    </system>
    <!-- 配置Mycat逻辑库与用户 -->
    <user name="mycat">
    <property name="password">mycat</property>
    <!-- 注意:这里配置的是逻辑数据库的名字 -->
    <property name="schemas">TESTDB</property>
</user> 
 </mycat:server>

schema.xml配置参数

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mycat:schema SYSTEM "schema.dtd">

<!-- 配置逻辑库 -->
<mycat:schema  xmlns:mycat="http://org.opencloudb/">
      <!-- 
        checkSQLschema:这个参数为False的时候,表明MyCAT会自动忽略掉表名前的数据库名。
        sqlMaxLimit:返回数据的行数限制,-1为不限制。
        dataNode:对应的分片。
      -->
  <schema name="TESTDB" checkSQLschema="true" sqlMaxLimit="100" dataNode="dn1">
      <!-- 
        table:配置逻辑表
        dataNode:数据的影响节点
        type:表的类型。global:全局表。 
      -->
      <table name="t_user" dataNode="dn1,dn2" rule="sharding-by-mod2"/>
      <table name="ht_jy_login_log" primaryKey="ID" dataNode="dn1,dn2" rule="sharding-by-date_jylog"/>
  </schema>
  <dataNode name="dn1" dataHost="localhost1" database="mycat_node1"/>
  <dataNode name="dn2" dataHost="localhost1" database="mycat_node2"/>
  <!-- 
    dataHost标签定义了具体的数据库实例、读写分离配置和心跳语句。 
    balance:负载均衡类型。
        0:不开启读写分离机制,所有读操作都发送到当前可用的writeHost上。
        1:全部的readHost与stand by writeHost参与select语句的负载均衡。
        2:所有读操作都随机在writeHost、readHost上分发。
        3:所有读请求随机分发到writeHost对应的readHost执行,writeHost不负担读压力。
    writeType:负载均衡类型。
        0:所有写操作发送到配置的第一个writeHost,当第一个writeHost宕机时,切换到第二个writeHost,重新启动后以切换后的为准,切换记录在配置文件:dnindex.properties中。
        1:所有写操作都随发送到配置的writeHost。
        2:尚未实现。
    switchType:切换方式。
        1:自动切换(默认)。
        -1:不自动切换。
        2:基于MySql主从同步的状态来决定是否切换。
    slaveThreshold:主从切换的阈值。当Seconds_Behind_Master 大于slaveThreshold时,读写分离筛选器会过滤掉此Slave机器,防止读到很久之前的旧数据,而当主节点宕机后,切换逻辑会检查Slave上的Seconds_Behind_Master是否为0,为0时则表示主从同步,可以安全切换,否则不会切换。
    maxCon:最大连接数。
    minCon:最小连接数。
    dbType:数据库的类型。可选值:mysql、postgresql、mongodb、oracle、spark、其它使用JDBC连接的数据库。
    dbDriver:指定数据库驱动。目前可选的值有native和JDBC。
    tempReadHostAvailable:writeHost失联后,其下面的readHost仍旧可用。默认0,可选值0、1。
  -->
  <dataHost name="localhost1" writeType="0" switchType="1" slaveThreshold="100" balance="1" dbType="mysql" maxCon="10" minCon="1" dbDriver="native">
    <!-- Mycat需要对物理库心跳检测的语句 -->
    <heartbeat>show status like 'wsrep%'</heartbeat>
    <!-- 
       writeHost:配置写主机。
       readHost:配置读主机。 
    -->
    <writeHost host="hostM1" url="127.0.0.1:3306" user="root" password="root" >
    </writeHost>  
  </dataHost>
</mycat:schema >

rule.xml配置示例

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mycat:rule SYSTEM "rule.dtd">

<mycat:rule  xmlns:mycat="http://org.opencloudb/">
  <!-- 
    tableRule:配置分片规则。
    name:schema.xml 中table 标签中对应的 rule="sharding-by-hour" ,也就是配置表的分片规则。
    columns:表的切分字段。
    algorithm:是规则对应的切分规则:映射到function 的name
  -->
  <tableRule name="sharding-by-hour">
    <rule>
      <columns>createTime</columns>
      <algorithm>sharding-by-hour</algorithm>
    </rule>
  </tableRule>
  
  <!-- 
    function:配置分片规则。
    name:切分规则的名称,名字任意取,但是需要与tableRule 中匹配。
    class:是切分规则对应的切分类,写死,需要哪种规则则配置哪种。
    property:切分规则对应的不同属性,不同的切分规则配置不同。
  -->
  <function name="sharding-by-hour" class="org.opencloudb.route.function.LatestMonthPartion">
    <property name="splitOneDay">24</property>
  </function>
   
</mycat:rule >

常用分片算法

分片算法 说明
简单取模(PartitionByMod) 适用于分片字段为整数类型的表,数据分布比较均匀
哈希取模(PartionByHashMod) 可以用于多种数据类型,可能会出现数据分布不均匀的情况
分片枚举(PartitionByFileMap) 可以根据可能的枚举值指定数据存储的位置
字符串范围取模分片(PartitionByPrefixPattern) 适用于分片字段为字符串类型的表(对字符串的前n个字符的ASCII码求和然后进行取模,然后根据取模值的范围确定数据存储位置)

MyCAT启动调试

1
2
$ cd logs
$ more wrapper.log

MyCAT验证配置

1
2
3
4
$ mysql -u用户名 -p密码 -P8066 -h主机IP
mysql> use 库名;
mysql> show tables;
mysql> select * from 表 limit 10;

运维

CentOS安装

安装说明

安装环境:Centos 7.2
软件:MyCAT 1.6 release

安装前提

系统中必须安装配置jdk1.7+。

安装步骤

下载

http://www.mycat.org.cn

解压

1
2
3
$ cd /usr/local
$ tar -zxvf Mycat-server-1.6-RELEASE-20161028204710-linux.tar.gz
$ chmod +x mycat      //配置可执行权限

配置

配置文件主要是:schema.xml、server.xml、rule.xml。
schema.xml中配置数据库的节点信息、分片规则、主从、读写分离、集群等。
server.xml中配置连接mycat的用户名密码及可以访问的数据库权限。
rule.xml中配置分片规则的规则定义及规则函数。

将mycat添加到环境变量

1
2
3
4
5
6
7
$ vi /etc/profile

# 添加以下内容:
export PATH="/usr/local/mycat/bin:$PATH"
# 保存退出

$ source /etc/profile

管理MyCAT

命令 说明
mycat start 启动
mycat stop 停止
mycat restart 重启
mycat status 查看状态
mycat dump dump运行
mycat console 行显

如果没有将MyCAT添加到环境变量,则需要

1
2
$ cd /usr/local/mycat/bin/
$ ./mycat start|stop|restart|status|console|dump

连接MyCAT

Mycat的数据端口:8066
Mycat的监控端口:9066

常用命令

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
# 显示所有命令
mysql> show @@help;

# 重载配置文件(重载配置期间,MyCAT是不可使用的)
mysql> reload @@config

# 显示逻辑库定义
mysql> show @@databases;
mysql> show @@databases where schema=逻辑库名称

# 查看数据节点(\G表示行内容按列的方式显示)
mysql> show @@datanode;
mysql> show @@datanode\G 

# 显示当前后端物理库的心跳检测情况,RS_CODE为1表示心跳正常,-1表示连接出错,-2表示连接超时,0表示初始化状态
mysql> show @@hearbeat;

# 显示当前前端客户端连接情况
mysql> show @@connection;

# 杀掉客户端的连接,参数为连接的ID值,通过show @@connection,可以展示当前连接到MyCAT的所有客户端进程,若某个进程异常,则可以通过该命令杀掉连接
mysql> kill @@CONNECTION 26907;

# 显示后端物理库连接信息,包括当前连接数,端口等信息。
mysql> show @@backend;

# 显示缓存的使用情况,对于性能监控和调优很有价值
mysql> show @@cache;

# 显示后端物理数据库的信息
mysql> show @@datasource; 

# 显示当前线程池的执行情况,是否有积压(active_count)以及task_queue_size,后者为积压的待处理的SQL,若积压数目一直保值,则说明后端物理连接可能不够或者SQL执行比较缓慢
mysql> show @@threadpool;

# 显示当前processors的处理情况,包括每个processor的IO吞吐量(NET_IN/NET_OUT)、IO队列的积压情况(R_QUEY/W_QUEUE),Socket Buffer Pool的使用情况 BU_PERCENT为已使用的百分比、BU_WARNS为Socket Buffer Pool不够时,临时创建的新的BUFFER的次数,若百分比经常超过90%并且BU_WARNS>0,则表明BUFFER不够,需要增大,参见性能调优手册。
mysql> show @@processor;

配置SQL防火墙

参数 默认 说明
selelctAllow true 是否允许执行SELECT语句
selectAllColumnAllow true 是否允许执行SELECT * FROM T这样的语句。
如果设置为false,不允许执行select * from t,但select * from (select id, name from t) a。
这个选项是防御程序通过调用select *获得数据表的结构信息。
selectIntoAllow true SELECT查询中是否允许INTO字句
deleteAllow true 是否允许执行DELETE语句
updateAllow true 是否允许执行UPDATE语句
insertAllow true 是否允许执行INSERT语句
replaceAllow true 是否允许执行REPLACE语句
mergeAllow true 是否允许执行MERGE语句,这个只在Oracle中有用callAllow
callAllow true 是否允许通过jdbc的call语法调用存储过程
setAllow true 是否允许使用SET语法
truncateAllow true truncate语句是危险,缺省打开,若需要自行关闭
createTableAllow true 是否允许创建表
alterTableAllow true 是否允许执行Alter Table语句
dropTableAllow true 是否允许修改表
commentAllow false 是否允许语句中存在注释,Oracle的用户不用担心,Wall能够识别hints和注释的区别
noneBaseStatementAllow false 是否允许非以上基本语句的其他语句,缺省关闭,通过这个选项就能够屏蔽DDL。
multiStatementAllow false 是否允许一次执行多条语句,缺省关闭
useAllow true 是否允许执行mysql的use语句,缺省打开
describeAllow true 是否允许执行mysql的describe语句,缺省打开
showAllow true 是否允许执行mysql的show语句,缺省打开
commitAllow true 是否允许执行commit操作
rollbackAllow true 是否允许执行roll back操作

如果把selectIntoAllow、deleteAllow、updateAllow、insertAllow、mergeAllow都设置为false,这就是一个只读数据源了。

使用MyCAT-WEB管理MyCAT

安装

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
# 安装jdk1.7+
$ 
# 安装Zookeeper
$ 
# 下载MyCAT-WEB
cd /usr/local
$ wget http://dl.mycat.io/mycat-web-1.0/Mycat-web-1.0-SNAPSHOT-20170102153329-linux.tar
$ tar zxvf Mycat-web-1.0-SNAPSHOT-20170102153329-linux.tar
$ vi mycat-web/mycat-web/WEB-INF/classes/mycat.properties
##### 配置Zookeeper 开始 #####

##### 配置Zookeeper 结束 #####
# 启动MyCAT-WEB
$ cd mycat-web
$ ./start.sh

访问:http://localhost:8082

配置高可用集群

环境说明

| 主机名 | IP | 操作系统 | 角色 |
| —- |:—-:|:—-:|
| node1 | 192.168.100.101 | CentOS7 | ZK |
| node2 | 192.168.100.102 | CentOS7 | ZK |
| node3 | 192.168.100.103 | CentOS7 | ZK |
| node4 | 192.168.100.104 | CentOS7 | HAProxy、keepalive |
| node5 | 192.168.100.105 | CentOS7 | HAProxy、keepalive |
| node6 | 192.168.100.106 | CentOS7 | MyCat |
| node7 | 192.168.100.107 | CentOS7 | MyCat |

安装步骤

安装jdk(nodeAll)

1
$ 

安装Zookeeper(node1、node2、node3)

1
$ 

安装HaProxy、keepalive(node4、node5)

1
$ 

安装MyCAT(node6、node7)

1
$ 

Wanglibing
Wanglibing
Engineer,Lifelong learner