欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

MyCat 分表分库 水平分片策略

程序员文章站 2022-03-09 09:13:00
...

MyCat 分表分库 水平分片策略

一、数据库分表分库策略

数据库分表分库原则遵循 垂直拆分与水平拆分垂直拆分是把不同的表拆到不同的数据库中,而水平拆分是把同一个表拆到不同的数据库中。相对于垂直拆分,水平拆分不是将表的数据做分类,而是按照某个字段的某种规则来分散到多个库之中,每个表中包含一部分数据。简单来说,我们可以将数据的水平切分理解为是按照数据行的切分,就是将表中 的某些行切分到一个数据库,而另外的某些行又切分到其他的数据库中,主要有分表,分库两种模式该方式提高了系统的稳定性跟负载能力,但是跨库join性能较差。

二、MyCat实现水平分片策略

MyCat支持10种分片策略:

  1. 求模算法
  2. 分片枚举
  3. 范围约定
  4. 日期指定
  5. 固定分片hash算法
  6. 通配取模
  7. ASCII码求模通配
  8. 编程指定
  9. 字符串拆分hash解析

三、使用MyCat根据地区实现水平分片策略

分片枚举这种规则适用于特定的场景,比如有些业务需要按照省份或区县来做保存,而全国的省份区县固定的,这类业务使用这一规则。

1.环境搭建

需搭准备三台服务器,一主一从一mycat虚拟数据库,具体配置可参考我博客:

https://blog.csdn.net/qq_43692950/article/details/107731431

2.创建数据库

在主数据库创建四个数据库db1 、 db2、db3 、db4,分别存放武汉、上海、苏州、其他地区,地区的数据。
然后分别在数据库中创建表user_info, 字段为id和name,name则存放地区属性。

MyCat 分表分库 水平分片策略

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表。
在表中插入一条语句:

MyCat 分表分库 水平分片策略
然后去从数据库,的db1数据库中查看数据:
MyCat 分表分库 水平分片策略
同理在mycat数据库插入其他数据,会根据我们定义的规则将数据放入不同表中。

如果在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表。
在表中插入一条语句:
MyCat 分表分库 水平分片策略
由于1%3=1,所以去db2数据库中查看:
MyCat 分表分库 水平分片策略
其他数据库都没有数据:
MyCat 分表分库 水平分片策略
MyCat 分表分库 水平分片策略
同理再以此添加数据会轮训分发给这三个数据库。
添加多个数据后,再mycat数据库查询的话:
MyCat 分表分库 水平分片策略
同样是拿到所有的数据。