Mycat 是什么?从定义和分类来看,它是一个开源的分布式数据库系统,是一个实现了MySQL 协议的的Server,前端用户可以把它看作是一个数据库代理,用MySQL 客户端工具和命令行访问,而其后端可以用MySQL 原生(Native)协议与多个MySQL 服务器通信,也可以用JDBC 协议与大多数主流数据库服务器通信,其核心功能是分表分库,即将一个大表水平分割为N 个小表,存储在后端MySQL 服务器里或者其他数据库里。
Mycat 发展到目前的版本,已经不是一个单纯的MySQL 代理了,它的后端可以支持MySQL、SQLServer、Oracle、DB2、PostgreSQL 等主流数据库,也支持MongoDB 这种新型NoSQL 方式的存储,未来还会支持更多类型的存储。而在最终用户看来,无论是那种存储方式,在Mycat 里,都是一个传统的数据库表,支持标准的SQL 语句进行数据的操作,这样一来,对前端业务系统来说,可以大幅降低开发难度,提升开发速度。
Mycat 的原理中最重要的一个动词是“拦截”,它拦截了用户发送过来的SQL 语句,首先对SQL 语句做了一些特定的分析:如分片分析、路由分析、读写分离分析、缓存分析等,然后将此SQL 发往后端的真实数据库,并将返回的结果做适当的处理,最终再返回给用户。当Mycat 收到一个SQL 时,会先解析这个SQL,查找涉及到的表,然后看此表的定义,如果有分片规则,则获取到SQL 里分片字段的值,并匹配分片函数,得到该SQL 对应的分片列表,然后将SQL 发往这些分片去执行,最后收集和处理所有分片返回的结果数据,并输出到客户端。
Mycat在逻率持上由几个模块组成:通信协议、路由解析、结果集处理、数据库连接、监控等模块。
主要流程:由通信协议模块的读写事件通知发起。读写事件通知具体的回调代码进行这次读写事件的处理。管理模块的执行流程由定时器事件进行资源检查和资源释放时发起,由客户端发送过来的数据通过协议解析、路由解析等流程进入执行组件。通过执行组把数据发送到通信协议模块,最终数据被写入目标数据库。由后端数据库返回数据,通过协议解析后发送至回调模块。如果是涉及多节点的数据,则执行流程将会先进入结果集汇聚、排序等模块中,然后将处理后的数据通过通信协议模块返回到客户端。如果有排序则是用的将结果集在mycat中进行了堆排序。
从原理上来看,可以把mycat 看成一个sql 转发器。mycat 接收到前端发来的sql,然后转发到后台的mysql 服务器上去执行。但是后面有很多台mysql 节点(如dn1,dn2,dn3),该转发到哪些节点呢?这就是路由解析该做的事情了。路由能保证sql 转发到正确的节点。转发的范围是刚刚好,不多发也不少发。在选型上,mycat使用的是druidparser。
MyCAT 是使用JAVA 语言进行编写开发,使用前需要先安装JAVA 运行环境(JRE),由于MyCAT 中使用了JDK7 中的一些特性,所以要求必须在JDK7 以上的版本上运行。同时Mysql建议使用5.5以上版本,5.6为宜。进入https://github.com/MyCATApache/Mycat-download,在列表中选择一个合适自己操作系统的包下载,然后解压在某个目录下。Mycat是个标准的Java程序,解压后即可运行。Linux下执行 mycat ,windows下执行 startup_nowrap.bat。
其中 bin 程序目录,存放了启动脚本,除了提供封装成服务的版本之外,也提供了nowrap 的脚本命令。conf 目录下存放配置文件,server.xml 是Mycat 服务器参数调整和用户授权的配置文件,schema.xml 是逻辑库定义和表以及分片定义的配置文件,rule.xml 是分片规则的配置文件,分片规则的具体一些参数信息单独存放为文件,也在这个目录下,配置文件修改,需要重启Mycat 或者通过9066 端口reload。lib 目录下主要存放mycat 依赖的一些jar 文件。日志存放在logs/mycat.log 中,每天一个文件,日志的配置是在conf/log4j.xml 中,根据自己的需要,可以调整输出级别为debug,debug 级别下,会输出更多的信息,方便排查问题。
主要配置文件为server.xml,schema.xml,rule.xml以及相应的分片规则。
server.xml用于配置系统参数、用户信息、访问权限及SQL防火墙和SQL拦截功能等。
system
标签配置 Mycat 的系统参数。
0
1
0
0
2
false
0
0
1
64k
1k
0
384m
false
user
标签配置Mycat的访问用户及权限。
123456
db1,db2
schema.xml用于配置逻辑库及逻辑表,配置逻辑表所存储的数据节点,配置数据节点所对应的物理数据库服务器信息。
定义了具体的数据库实例、读写分离配置和心跳语句。
select user()
select user()
,Oracle可以使用select 1 from dual
等。writeHost
配置写实例(master)、readHost
配置读实例(salve),并且readHost
为writeHost
的子标签。通过这两个标签可以组合读/写实例以满足系统的要求。在一个dataHost
内可以定义多个writeHost
和readHost
。但是,如果writeHost
指定的后端数据库宕机,那么这个writeHost
绑定的所有readHost
都将不可用。另一方面,当一个writeHost
宕机时系统会自动检测到,并切换到备用的writeHost
上去。定义了 MyCat 中的数据节点,也就是我们通常说所的数据分片。一个 dataNode 标签就是一个独立的数据分片。
定义 MyCat 实例中的逻辑库,MyCat 可以有多个逻辑库,每个逻辑库都有自己的相关配置。可以使用 schema 标签来划分这些不同的逻辑库。
定义了 MyCat 中的逻辑表,所有需要拆分的表都需要在这个标签中定义。其中 childTable 标签用于定义 E-R 分片的子表。通过标签上的属性与父表进行关联。
属性 | 说明 |
---|---|
name | 该属性定义逻辑表的表名 |
dataNode | 该属性定义这个逻辑表所属的 dataNode, 该属性的值需要和 dataNode 标签中 name 属性的值相互对应。 |
rule | 该属性用于指定逻辑表要使用的规则名字,规则名字在 rule.xml 中定义,必须与 tableRule 标签中 name 属性属性值一一对应 |
ruleRequired | 该属性用于指定表是否绑定分片规则,如果配置为 true,但没有配置具体 rule 的话 ,程序会报错。 |
primaryKey | 该逻辑表对应真实表的主键 |
type | 该属性定义了逻辑表的类型,目前逻辑表只有“全局表”和”普通表”两种类型。全局表定义type=”global”,不定义的就是普通表。 |
autoIncrement | 主键是否自增长。 |
subTables | 分表,分表目前不支持Join。 |
needAddLimit | 是否自动添加limit,默认是开启状态。 |
这里定义了一个逻辑表user表及其子表user_log,分片规则为user-mod-long,一个全局表area。
定义了我们对表进行拆分所涉及到的规则定义。
属性 name指定唯一的名字,用于标识不同的表规则。内嵌的 rule 标签则指定对物理表中的哪一列进行拆分和使用什么路由算法。
id
mod-long
定义了tableRule中使用的分片算法。
3
常用的几个分片算法:
PartitionByMod
:简单取模,直接通过列值进行取模得出分片位置PartitionByHashMod
:哈希取模,先将列值进行hash运算之后再取模得出分片位置PartitionByFileMap
:分片枚举,根据枚举值对数据进行分片,例如在异地多活的场景中通过地区id进行数据分片的场景PartitionByPrefixPattern
:字符串范围取模,根据长字符串的前面几位进行取模分片