Mycat是数据库分库分表的中间件,Mycat使用最多的两个功能是:读写分离和分库分表功能,支持全局表和E-R关系(这两个比较实用)
mycat相当于是一个代理,可以将多个实际数据库组合成一个完整的虚拟数据库
我们可以直接访问mycat的端口,其使用的是mysql原生的协议连接数据库进行通信
mycat主要用来解决水平拆分的问题,因为水平拆分和架构无关数据量大了就必须要做,而垂直拆分更多的是架构设计的问题
配置mycat可以实现分库分表
配置文件:
- rule.xml :配置分片规则
- schema.xml:配置逻辑数据库逻辑表
- server.xml:配置mycat自身逻辑数据库的配置,例如用户名密码等
类似mycat的有TDDL、Sharding-JDBC、cobar
mycat核心概念:
MyCAT通过定义表的分片规则来实现分片,每个表格可以捆绑一个分片规则,每个分片规则指定一个分片字段并绑定一个函数,来实现动态分片算法
1.Schema:逻辑库,与MySQL中的Database(数据库)对应,一个逻辑库中定义了所包括的Table,schema可以有多个,具体配置如下:
<schema name="TESTDB" checkSQLschema="false" sqlMaxLimit="100">
<table name="news" primaryKey="ID" subTables="news$1-3" dataNode="dn1" rule="mod-long" />
《-- rule 分片规则, subTables="news$1-3" 数据表存储在数据库dn1的news1,news2,news3表中 --》
<table name="customer" primaryKey="ID" dataNode="dn1,dn2" rule="sharding-by-intfile">
《-- dataNode="dn1,dn2" ,一张表存在于多个数据库里--》
<childTable name="orders" primaryKey="ID" joinKey="customer_id" parentKey="id">
<childTable name="order_items" joinKey="order_id" parentKey="id" />
</childTable>
<childTable name="customer_addr" primaryKey="ID" joinKey="customer_id" parentKey="id" />
</table>
</schema>
2.Table:逻辑表,即物理数据库中存储的某一张表,与传统数据库不同,这里的表格需要声明其所存储的逻辑数据节点DataNode。在此可以指定表的分片规则。
3.DataNode:MyCAT的逻辑数据节点,是存放table的具体物理节点,也称之为分片节点(也就是物理数据库),通过DataSource来关联到后端某个具体数据库上 ,如下所示:
<dataNode name="dn1" dataHost="localhost1" database="db1" />
《--datahost指的是服务器端口是一个连接,database是一个数据库一个服务器可以有多个数据库--》
<dataNode name="dn2" dataHost="localhost1" database="db2" />
<dataNode name="dn3" d ataHost="localhost1" database="db3" />
<dataHost name="localhost1" maxCon="1000" minCon="10" balance="0"
writeType="0" dbType="mysql" dbDriver="native" switchType="1" slaveThreshold="100">
<heartbeat>select user()</heartbeat>
<!-- 可以有多个writeHost子节点,两个writeHost是双主配置 -->
<writeHost host="hostM1" url="localhost:3306" user="root" password="123456">
<!-- 可以有多个readHost子节点 -->
<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="hostM2" url="localhost:3316" user="root" password="123456"/> -->
</dataHost>
**4.DataSource:**定义某个物理库的访问地址,用于捆绑到Datanode上
5.dataHost 物理数据库配置
6.ER表
<childTable name="orders" primaryKey="ID" joinKey="customer_id"
parentKey="id">
</childTable>
childTable是附属于其父表,也就是说子表和父表之间存在关联关系,mycat会将子表和父表关联数据存放在同一个节点上
分片规则 rule.xml
<tableRule name="rule1">
<rule>
<columns>id</columns>
<algorithm>func1</algorithm>
</rule>
</tableRule>
操作
分片表 在schema,xml里面定义的分片表如下:
<table name="hotnews" primaryKey="ID" autoIncrement="true" dataNode="dn1,dn2,dn3"
rule="mod-long" />
上面的代码定义了一个逻辑分片表hotnews,声明了其数据分别存储于数据节点dn1,dn2,dn3里面
分片规则定义在rule.xml中,mod-long是将id作为分片键,按照某个数进行取模,动态计算数据应该存放在何处
全局表 在schema,xml里面定义的全局表如下:
<table name="company" primaryKey="ID" type="global" dataNode="dn1,dn2,dn3" />
company表是全局表,通过mycat对全局表的操作所有的数据节点都会同步改变
使用示例:
例如:我们将一张user表拆分成了三张,根据一定规则路由,假如插入了六条数据
当我们使用select * from user
mycat会给语句加上limit100,然后从三张表中加载数据,组合起来返回
如果使用select * from user where id = 1;
mycat会路由到指定的表,因为我们定义的id是分片键
但是如果使用查询语句select * from user where name = ‘xxx’;
mycat无法使用路由,会在三个数据表中都执行查询语句
因此在定义分片键的时候需要考虑这个问题
分片方式
1.连续分片
日期,数字范围等
例如:
在rule.xml里面有定义例如sharding-by-month按月分片
<function name="rang-long"
class="io.mycat.route.function.AutoPartitionByLong">
<property name="mapFile">autopartition-long.txt</property>
</function>
按照数字范围进行划分,具体的划分规则例如 0-- 10000 放在第1个,10001-20000放在第二个分片
2.离散分片
取模,枚举,hash等
3.综合分片
先取模,然后再定义范围
分片总结
1.根据业务数据特性选择分片规则
2.善用全局表,ER关系表解决join操作
3.用好primaryKey让性能起飞
mycat注解
mycat是无法执行函数的,那么怎么办呢?
可以使用mycat注解直接指定函数语句需要在哪个节点执行,mycat识别到指定注解的时候会直接把后面的SQL语句发送到指定的节点解析执行
例如:
/*!mycat:sql=select * from users where userId =1*/ select fun() from dual;
mycat关联查询
1.用好ER表
2.善用全局表
3.使用注解
/*!mycat:catlet=io.mycat.catlets.ShareJioin*/
目前只支持两张表的关联查询