阅读 754

Mycat中的特性----数据分片

haha,首先这不是一篇入门Mycat的博客但小编感觉又很入门的博客!这篇博客主要讲解Mycat中数据分片的相关知识,同时小编将会在本机数据库上进行测试验证,图文并茂展示出来。

数据库分区分表,咋一听非常地高大上,总有一种高高在上,望尘莫及的感觉,但小编想说的是,其实,作为一个开发人员,该来的总是会来,该学的东西你还是得学,区别只是时间先后顺序的问题。

一、分区分表

分区就是把一个数据表的文件和索引分散存储在不同的物理文件中,和分片的区别在于分区作用在单台物理主机单个数据库。

mysql支持的分区类型包括Range、List、Hash、Key,其中Range比较常用:

RANGE分区:基于属于一个给定连续区间的列值,把多行分配给分区。

LIST分区:类似于按RANGE分区,区别在于LIST分区是基于列值匹配一个离散值集合中的某个值来进行选择。

HASH分区:基于用户定义的表达式的返回值来进行选择的分区,该表达式使用将要插入到表中的这些行的列值进行计算。这个函数可以包含MySQL 中有效的、产生非负整数值的任何表达式。

KEY分区:类似于按HASH分区,区别在于KEY分区只支持计算一列或多列,且MySQL服务器提供其自身的哈希函数。必须有一列或多列包含整数值。

分表是指在逻辑上将一个表拆分成多个逻辑表,在整体上看是一张表,分表有水平拆分和垂直拆分两种,举个例子,将一张大的存储商户信息的表按照商户号的范围进行分表,将不同范围的记录分布到不同的表中。

二、Mycat 数据分片Sharding的种类

Mycat 的分片其实和分表差不多意思,就是当数据库过于庞大,尤其是写入过于频繁且很难由一台主机支撑时,这时数据库就会面临瓶颈。我们将存放在同一个数据库实例中的数据分散存放到多个数据库实例(主机)上,进行多台设备存取以提高性能,在切分数据的同时可以提高系统的整体性。

数据分片是指将数据全局地划分为相关的逻辑片段,有水平切分、垂直切分、混合切分三种类型,下面主要讲下Mycat的水平和垂直切分。有一点很重要,那就是Mycat是分布式的,因此分出来的数据片分布到不同的物理机上是正常的,靠网络通信进行协作。

水平切分

就是按照某个字段的某种规则分散到多个节点库中,每个节点中包含一部分数据。可以将数据水平切分简单理解为按照数据行进行切分,就是将表中的某些行切分到一个节点,将另外某些行切分到其他节点,从分布式的整体来看它们是一个整体的表。

垂直切分

一个数据库由很多表构成,每个表对应不同的业务,垂直切分是指按照业务将表进行分类并分不到不同的节点上。垂直拆分简单明了,拆分规则明确,应用程序模块清晰、明确、容易整合,但是某个表的数据量达到一定程度后扩展起来比较困难。

混合切分

为水平切分和垂直切分的结合。

三、Mycat 垂直切分、水平切分实战

1、垂直切分

上面说到,垂直切分主要是根据具体业务来进行拆分的,那么,我们可以想象这么一个场景,假设我们有一个非常大的电商系统,那么我们需要将订单表、流水表、用户表、用户评论表等分别分不到不同的数据库中来提高吞吐量,架构图大概如下:

由于小编是在一台机器上测试,因此就只有host1这个节点,但不同的表还是依旧对应不同的数据库,只不过是所有数据库属于同一个数据库实例(主机)而已,后期不同主机只需增加<dataHost>节点即可。

mycat配置文件如下:

server.xml

<user name="root">
    <property name="password">root</property>
    // 对应四个逻辑库
    <property name="schemas">order,trade,user,comment</property>
</user>
复制代码

schema.xml

<?xml version="1.0"?>
<!DOCTYPE mycat:schema SYSTEM "schema.dtd">
<mycat:schema xmlns:mycat="http://io.mycat/">
    
    <!-- 4个逻辑库,对应4个不同的分片节点 -->
    <schema name="order" checkSQLschema="false" sqlMaxLimit="100" dataNode="database1" />
    <schema name="trade" checkSQLschema="false" sqlMaxLimit="100" dataNode="database2" />
    <schema name="user" checkSQLschema="false" sqlMaxLimit="100" dataNode="database3" />
    <schema name="comment" checkSQLschema="false" sqlMaxLimit="100" dataNode="database4" />

    <!-- 四个分片,对应四个不同的数据库 -->
    <dataNode name="database1" dataHost="localhost1" database="database1" />
    <dataNode name="database2" dataHost="localhost1" database="database2" />
    <dataNode name="database3" dataHost="localhost1" database="database3" />
    <dataNode name="database4" dataHost="localhost1" database="database4" />
    
    <!-- 实际物理主机,只有这一台 -->
    <dataHost name="localhost1" maxCon="1000" minCon="10" balance="0"
                writeType="0" dbType="mysql" dbDriver="native" switchType="1"  slaveThreshold="100">
        <heartbeat>select user()</heartbeat>
        <writeHost host="hostM1" url="localhost:3306" user="root"
                password="root">
        </writeHost>
    </dataHost>
</mycat:schema>
复制代码

登陆本机mysql,创建order,trade,user,comment4个数据库:

create database database1 character set utf8;
create database database2 character set utf8;
create database database3 character set utf8;
create database database4 character set utf8;
复制代码

执行bin目录下的startup_nowrap.bat文件,如果输出下面内容,则说明已经启动mycat成功,如果没有,请检查order,trade,user,comment4个数据库是否已经创建。

采用下面语句登陆Mycat服务器:

mysql -uroot -proot -P8066 -h127.0.0.1

comment数据库中创建Comment表,并插入一条数据

上图1处新建一个Comment表,2处插入一条记录,3处查看记录插入到哪个数据节点中,即database4

2、水平切分

server.xml

<user name="root">
    <property name="password">root</property>
    <property name="schemas">TESTDB</property>
</user>
复制代码

schema.xml

<?xml version="1.0"?>
<!DOCTYPE mycat:schema SYSTEM "schema.dtd">
<mycat:schema xmlns:mycat="http://io.mycat/">
    <schema name="TESTDB" checkSQLschema="false" sqlMaxLimit="100">
        <table name="travelrecord" dataNode="dn1,dn2,dn3" rule="auto-sharding-long" />
    </schema>

    <dataNode name="dn1" dataHost="localhost1" database="db1" />
    <dataNode name="dn2" dataHost="localhost1" database="db2" />
    <dataNode name="dn3" dataHost="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>
    <!-- can have multi write hosts -->
    <writeHost host="hostM1" url="localhost:3306" user="root"
       password="root">
    </writeHost>
    </dataHost>
</mycat:schema>
复制代码

rule.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mycat:rule SYSTEM "rule.dtd">
<mycat:rule xmlns:mycat="http://io.mycat/">
    <tableRule name="auto-sharding-long">
        <rule>
            <columns>id</columns>
            <algorithm>rang-long</algorithm>
        </rule>
    </tableRule>

    <function name="rang-long"
            class="io.mycat.route.function.AutoPartitionByLong">
        <property name="mapFile">autopartition-long.txt</property>
    </function>
</mycat:rule>
复制代码

conf目录下的autopartition-long.txt

# range start-end ,data node index
# K=1000,M=10000.
0-500M=0
500M-1000M=1
1000M-1500M=2
复制代码

上面的配置创建了一个名为TESTDB的逻辑库,并指定了需要切分的表<table>标签,表名为travelrecord,分区的策略采用rang-long算法,即根据id数据列值的范围进行切分,具体的规则在autopartition-long.txt文件中定义,即id0-500*10000范围内的记录存放在db1travelrecord表中,id500*10000 - 1000*10000范围内的记录存放在db2数据库的travelrecord表中,下面我们插入两条数据,验证是否和分片规则一致。

创建db1,db2,db3数据库

create database db1 character set utf8;
create database db2 character set utf8;
create database db3 character set utf8;
复制代码

登陆Mycat服务器

mysql -uroot -proot -P8066 -h127.0.0.1

创建travelrecord表并插入id等于1,id等于5000010两条记录

创建数据表后,数据库结构如下:

插入两条记录:

可以看到,id等于1的记录被插入到db1中,id等于5000010的记录被插入到db2中,那么数据库是否真的是这样呢?

确实是这样的,到此我们就完成了mycat数据库的水平切分,这个例子只是演示按照id列值得范围进行切分,mycat还支持很多的分片算法,如取模、一致性哈希算法、按日期分片算法等等,大家可以看《分布式数据库架构及企业实战----基于Mycat中间件》这本书深入学习。