MyCat 分表分库 水平分片策略
MyCat 分表分库 水平分片策略
一、数据库分表分库策略
数据库分表分库原则遵循 垂直拆分与水平拆分垂直拆分是把不同的表拆到不同的数据库中,而水平拆分是把同一个表拆到不同的数据库中。相对于垂直拆分,水平拆分不是将表的数据做分类,而是按照某个字段的某种规则来分散到多个库之中,每个表中包含一部分数据。简单来说,我们可以将数据的水平切分理解为是按照数据行的切分,就是将表中 的某些行切分到一个数据库,而另外的某些行又切分到其他的数据库中,主要有分表,分库两种模式该方式提高了系统的稳定性跟负载能力,但是跨库join性能较差。
二、MyCat实现水平分片策略
MyCat支持10种分片策略:
- 求模算法
- 分片枚举
- 范围约定
- 日期指定
- 固定分片hash算法
- 通配取模
- ASCII码求模通配
- 编程指定
- 字符串拆分hash解析
三、使用MyCat根据地区实现水平分片策略
分片枚举这种规则适用于特定的场景,比如有些业务需要按照省份或区县来做保存,而全国的省份区县固定的,这类业务使用这一规则。
1.环境搭建
需搭准备三台服务器,一主一从一mycat虚拟数据库,具体配置可参考我博客:
https://blog.csdn.net/qq_43692950/article/details/107731431
2.创建数据库
在主数据库创建四个数据库db1 、 db2、db3 、db4,分别存放武汉、上海、苏州、其他地区,地区的数据。
然后分别在数据库中创建表user_info, 字段为id和name,name则存放地区属性。
3.修改mycat conf/partition-hash-int.txt 规则
wuhan=0
shanghai=1
suzhou=2
other=3
4.修改 conf/rule.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mycat:rule SYSTEM "rule.dtd">
<mycat:rule xmlns:mycat="http://io.mycat/">
<tableRule name="role2"> <!-- 规则名 -->
<rule>
<columns>name</columns> <!-- 使用数据库的name字段定义规则-->
<algorithm>hash-int</algorithm>
</rule>
</tableRule>
<function name="hash-int" class="io.mycat.route.function.PartitionByFileMap">
<property name="mapFile">partition-hash-int.txt</property> <!-- 指向上面配置的文件-->
<property name="type">1</property> <!-- 1代表非整型,0代表整形,我们上面配置的为拼音字母所以是1-->
<property name="defaultNode">3</property> <!-- 如果没有上面的规则,则默认存在哪个里面,这里选other-->
</function>
</mycat:rule>
5.修改 conf/schema.xml
<?xml version="1.0"?>
<!DOCTYPE mycat:schema SYSTEM "schema.dtd">
<mycat:schema xmlns:mycat="http://io.mycat/">
<!-- TESTDB1 是mycat的逻辑库名称,链接需要用的 -->
<schema name="mycat_testdb" checkSQLschema="false" sqlMaxLimit="100" dataNode="dn1">
<table name="user_info" dataNode="dn1,dn2,dn3" rule="role2" />
</schema>
<!-- database 是MySQL数据库的库名 -->
<dataNode name="dn1" dataHost="localhost1" database="db1" />
<dataNode name="dn2" dataHost="localhost1" database="db2" />
<dataNode name="dn3" dataHost="localhost1" database="db3" />
<!--
dataNode节点中各属性说明:
name:指定逻辑数据节点名称;
dataHost:指定逻辑数据节点物理主机节点名称;
database:指定物理主机节点上。如果一个节点上有多个库,可使用表达式db$0-99, 表示指定0-99这100个数据库;
dataHost 节点中各属性说明:
name:物理主机节点名称;
maxCon:指定物理主机服务最大支持1000个连接;
minCon:指定物理主机服务最小保持10个连接;
writeType:指定写入类型;
0,只在writeHost节点写入;
1,在所有节点都写入。慎重开启,多节点写入顺序为默认写入根据配置顺序,第一个挂掉切换另一个;
dbType:指定数据库类型;
dbDriver:指定数据库驱动;
balance:指定物理主机服务的负载模式。
0,不开启读写分离机制;
1,全部的readHost与stand by writeHost参与select语句的负载均衡,简单的说,当双主双从模式(M1->S1,M2->S2,并且M1与 M2互为主备),正常情况下,M2,S1,S2都参与select语句的负载均衡;
2,所有的readHost与writeHost都参与select语句的负载均衡,也就是说,当系统的写操作压力不大的情况下,所有主机都可以承担负载均衡;
-->
<dataHost name="localhost1" maxCon="1000" minCon="10" balance="3" writeType="0" dbType="mysql" dbDriver="native" switchType="1" slaveThreshold="100">
<heartbeat>select user()</heartbeat>
<!-- 可以配置多个主从 -->
<writeHost host="hostM1" url="192.168.2.120:3306" user="root" password="root">
<!-- 可以配置多个从库 -->
<readHost host="hostS2" url="192.168.2.121:3306" user="root" password="root" />
</writeHost>
</dataHost>
</mycat:schema>
6.修改 conf/server.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mycat:server SYSTEM "server.dtd">
<mycat:server xmlns:mycat="http://io.mycat/">
<!-- 读写都可用的用户 -->
<user name="root" defaultAccount="true">
<property name="password">123456</property>
<property name="schemas">mycat_testdb</property>
<!-- 表级 DML 权限设置 -->
<!--
<privileges check="false">
<schema name="TESTDB" dml="0110" >
<table name="tb01" dml="0000"></table>
<table name="tb02" dml="1111"></table>
</schema>
</privileges>
-->
</user>
<!-- 只读用户 -->
<user name="user">
<property name="password">user</property>
<property name="schemas">mycat_testdb</property>
<property name="readOnly">true</property>
</user>
</mycat:server>
7.启动 mycat
进入bin:
./mycat start
8.测试
使用NaviCat连接,Mycat数据库,即可看到user_info表。
在表中插入一条语句:
然后去从数据库,的db1数据库中查看数据:
同理在mycat数据库插入其他数据,会根据我们定义的规则将数据放入不同表中。
如果在mycat数据库执行查询的话,可以见到mycat已经自动帮我们整理好了所有数据;
四、使用MyCat根据id取模实现水平分片策略
求摸法分片,根据id进行十进制求摸运算,运算结果为分区索引
注意:数据库节点分片数量无法更改。 和ES集群非常相似的。
还是使用上面创建的数据库,但这次只用db1、db2、db3三个数据库做分片集群。
1.修改 conf/rule.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mycat:rule SYSTEM "rule.dtd">
<mycat:rule xmlns:mycat="http://io.mycat/">
<tableRule name="role1">
<rule>
<columns>id</columns> <!--根据数据库的那个字段做依据-->
<algorithm>mod-long</algorithm>
</rule>
</tableRule>
<function name="mod-long" class="io.mycat.route.function.PartitionByMod">
<!--指定分片数量(数据库的数量),不可以被更改-->
<property name="count">3</property>
</function>
</mycat:rule>
2.修改 conf/schema.xml
<?xml version="1.0"?>
<!DOCTYPE mycat:schema SYSTEM "schema.dtd">
<mycat:schema xmlns:mycat="http://io.mycat/">
<!-- TESTDB1 是mycat的逻辑库名称,链接需要用的 -->
<schema name="mycat_testdb" checkSQLschema="false" sqlMaxLimit="100" dataNode="dn1">
<table name="user_info" dataNode="dn1,dn2,dn3" rule="role1"/>
</schema>
<!-- database 是MySQL数据库的库名 -->
<dataNode name="dn1" dataHost="localhost1" database="db1" />
<dataNode name="dn2" dataHost="localhost1" database="db2" />
<dataNode name="dn3" dataHost="localhost1" database="db3" />
<!--
dataNode节点中各属性说明:
name:指定逻辑数据节点名称;
dataHost:指定逻辑数据节点物理主机节点名称;
database:指定物理主机节点上。如果一个节点上有多个库,可使用表达式db$0-99, 表示指定0-99这100个数据库;
dataHost 节点中各属性说明:
name:物理主机节点名称;
maxCon:指定物理主机服务最大支持1000个连接;
minCon:指定物理主机服务最小保持10个连接;
writeType:指定写入类型;
0,只在writeHost节点写入;
1,在所有节点都写入。慎重开启,多节点写入顺序为默认写入根据配置顺序,第一个挂掉切换另一个;
dbType:指定数据库类型;
dbDriver:指定数据库驱动;
balance:指定物理主机服务的负载模式。
0,不开启读写分离机制;
1,全部的readHost与stand by writeHost参与select语句的负载均衡,简单的说,当双主双从模式(M1->S1,M2->S2,并且M1与 M2互为主备),正常情况下,M2,S1,S2都参与select语句的负载均衡;
2,所有的readHost与writeHost都参与select语句的负载均衡,也就是说,当系统的写操作压力不大的情况下,所有主机都可以承担负载均衡;
-->
<dataHost name="localhost1" maxCon="1000" minCon="10" balance="3" writeType="0" dbType="mysql" dbDriver="native" switchType="1" slaveThreshold="100">
<heartbeat>select user()</heartbeat>
<!-- 可以配置多个主从 -->
<writeHost host="hostM1" url="192.168.0.105:3306" user="root" password="root">
<!-- 可以配置多个从库 -->
<readHost host="hostS2" url="192.168.0.106:3306" user="root" password="root" />
</writeHost>
</dataHost>
</mycat:schema>
3.server.xml
server.xml和上面配的一样,无需改动。
4.启动mycat
进入bin:
./mycat start
5.测试
使用NaviCat连接,Mycat数据库,即可看到user_info表。
在表中插入一条语句:
由于1%3=1,所以去db2数据库中查看:
其他数据库都没有数据:
同理再以此添加数据会轮训分发给这三个数据库。
添加多个数据后,再mycat数据库查询的话:
同样是拿到所有的数据。