Mycat -04 分片续集

范围分片auto_sharding_long

1.schema.xml

        <schema name="TESTDB" checkSQLschema="false" sqlMaxLimit="100" dataNode="dn1">
                <table name="employee" primaryKey="ID" dataNode="dn1,dn2,dn3"
                           rule="sharding-by-intfile" />
                <table name="auto_sharding" primaryKey="ID" 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="1"
                          writeType="0" dbType="mysql" dbDriver="native" switchType="1"  slaveThreshold="100">
                <heartbeat>select user()</heartbeat>
                <!-- can have multi write hosts -->
                <writeHost host="hostM1" url="10.1.3.67:3606" user="mycat"
                                   password="123456">
                        <!-- can have multi read hosts -->
                        <readHost host="hostS1" url="10.1.3.68:3606" user="mycat" password="123456" />
                        <readHost host="hostS2" url="10.1.3.69:3606" user="mycat" password="123456" />
                </writeHost>
        <!--    <writeHost host="hostS1" url="10.1.3.69:3606" user="mycat"
                                   password="123456" />  -->
        </dataHost>

2.rule.xml

    <tableRule name="auto-sharding-long">  
        <rule>  
            <columns>idcolumns>  
            <algorithm>rang-long</algorithm>  
        </rule>  
    </tableRule>  
    <function name="rang-long"  
        class="io.mycat.route.function.AutoPartitionByLong">  
        <property name="mapFile">fun/autopartition-long.txt</property>  
        <property name="defaultNode">0</property>  
    </function>  

3.autopartition-long.txt

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

4.登录8066 ,建表测试

create table auto_sharding (id int primary key , name varchar(10));
mysql> insert into auto_sharding(id,name) values (1,database());
mysql> insert into auto_sharding(id,name) values (2,database());
mysql> insert into auto_sharding(id,name) values (8000000,database());   
Query OK, 1 row affected (0.00 sec)
mysql> insert into auto_sharding(id,name) values (10000000,database());   
Query OK, 1 row affected (0.01 sec)
mysql> insert into auto_sharding(id,name) values (12000000,database());  
Query OK, 1 row affected (0.00 sec)
mysql> insert into auto_sharding(id,name) values (15000000,database()); 
Query OK, 1 row affected (0.00 sec)
mysql> select * from auto_sharding;
+----------+------+
| id       | name |
+----------+------+
|  8000000 | db2  |
| 10000000 | db2  |
|     -100 | db1  |
|        1 | db1  |
|        2 | db1  |
|  1200000 | db1  |
|  1400000 | db1  |
| 12000000 | db3  |
| 15000000 | db3  |
+----------+------+

mysql> explain select * from auto_sharding;
+-----------+---------------------------------------+
| DATA_NODE | SQL                                   |
+-----------+---------------------------------------+
| dn1       | SELECT * FROM auto_sharding LIMIT 100 |
| dn2       | SELECT * FROM auto_sharding LIMIT 100 |
| dn3       | SELECT * FROM auto_sharding LIMIT 100 |
+-----------+---------------------------------------+

 按天数分片 sharding-by-day

schema.xml

<mycat:schema xmlns:mycat="http://io.mycat/">

        <schema name="TESTDB" checkSQLschema="false" sqlMaxLimit="100" dataNode="dn1">

                <table name="company" primaryKey="ID" type="global" dataNode="dn1,dn2,dn3" />
                <!-- random sharding using mod sharind rule -->
                <table name="hotnews" primaryKey="ID" autoIncrement="true" dataNode="dn1,dn2,dn3"
                           rule="mod-long" />
                <table name="employee" primaryKey="ID" dataNode="dn1,dn2,dn3"
                           rule="sharding-by-intfile" />
                <table name="auto_sharding" primaryKey="ID" dataNode="dn1,dn2,dn3"
                           rule="auto-sharding-long" />
                <table name="sharding_day" primaryKey="ID" dataNode="dn1,dn2,dn3"
                           rule="sharding-by-day" />
        </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="1"
                          writeType="0" dbType="mysql" dbDriver="native" switchType="1"  slaveThreshold="100">
                <heartbeat>select user()</heartbeat>
                <!-- can have multi write hosts -->
                <writeHost host="hostM1" url="10.1.3.67:3606" user="mycat"
                                   password="123456">
                        <!-- can have multi read hosts -->
                        <readHost host="hostS1" url="10.1.3.68:3606" user="mycat" password="123456" />
                        <readHost host="hostS2" url="10.1.3.69:3606" user="mycat" password="123456" />
                </writeHost>
        <!--    <writeHost host="hostS1" url="10.1.3.69:3606" user="mycat"
                                   password="123456" />  -->
        </dataHost>
</mycat:schema>

rule.xml

<tableRule name="sharding-by-day">
        <rule>
                <columns>create_time</columns>
                <algorithm>part-by-day</algorithm>
        </rule>
</tableRule>

<function name="part-by-day"
        class="io.mycat.route.function.PartitionByDate">
        <property name="dateFormat">yyyy-MM-dd</property>
        <property name="sBeginDate">2018-03-18</property> 
        <property name="sPartionDay">10</property>         # 10天一个分区
</function>

开始时间为2018-03-18,如果未设置结束时间,则时间范围超出三个分片后就报错。但是插入开始时间之前的不会报错。
如果设置了结束的时间sEndDate,则代表数据达到了这个日期的分片后后循环从开始分片插入。

注意事项:  

schema里的table的dataNode节点个数必须:大于rule的开始时间按照分片天数计算到现在的个数

(如开始时间:2017-10-01.分片天数为:每10天一个分片,当前时间为:2017-10-31 那么dataNode的节点必须大于等于4个)

登录8066 测试验证

CREATE TABLE `sharding_day` (
  `id` int(11) NOT NULL,
  `create_time` timestamp NULL DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP,
  `name` varchar(20) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

插入数据(第一条为开始时间之前的) mysql
> insert into sharding_day (id,create_time,name ) values (1,'2018-03-11',database()); Query OK, 1 row affected (0.02 sec) mysql> insert into sharding_day (id,create_time,name ) values (2,'2018-03-18',database()); Query OK, 1 row affected (0.01 sec) mysql> insert into sharding_day (id,create_time,name ) values (3,'2018-03-28',database()); Query OK, 1 row affected (0.01 sec) mysql> insert into sharding_day (id,create_time,name ) values (4,'2018-04-08',database()); Query OK, 1 row affected (0.02 sec) mysql> insert into sharding_day (id,create_time,name ) values (5,'2018-04-10',database()); Query OK, 1 row affected (0.00 sec) mysql> insert into sharding_day (id,create_time,name ) values (5,'2018-04-18',database()); ERROR 1064 (HY000): Can't find a valid data node for specified node index :SHARDING_DAY -> CREATE_TIME -> 2018-04-18 -> Index : 3 未设置sEnddate ,超过了分片的个数就会报错

mysql> select * from sharding_day; +----+---------------------+------+ | id | create_time | name | +----+---------------------+------+ | 1 | 2018-03-11 00:00:00 | db1 | | 4 | 2018-04-08 00:00:00 | db3 | | 5 | 2018-04-10 00:00:00 | db3 | | 3 | 2018-03-28 00:00:00 | db2 | | 2 | 2018-03-18 00:00:00 | db1 | +----+---------------------+------+

按照自然月分片sharding-by-month

schema.xml 

       <schema name="TESTDB" checkSQLschema="false" sqlMaxLimit="100" dataNode="dn1">
                <table name="sharding_month" primaryKey="ID" dataNode="dn1,dn2,dn3"
                           rule="sharding-by-month" />
    </schema>

rule.xml

<tableRule name="sharding-by-month">
        <rule>
                <columns>create_time</columns>
                <algorithm>partbymonth</algorithm>
        </rule>
</tableRule>


<function name="partbymonth"
        class="io.mycat.route.function.PartitionByMonth">
        <property name="dateFormat">yyyy-MM-dd</property>
        <property name="sBeginDate">2018-03-01</property>
        <property name="sEndDate">2018-05-31</property>
</function>

schema里的table的dataNode节点个数必须:大于rule的开始时间按照分片数计算到现在的个数

登录8066 测试验证

mysql> create table sharding_month(id int primary key ,create_time  timestamp null on update current_timestamp , name varchar(20));
Query OK, 0 rows affected (0.12 sec)
mysql> desc sharding_month;
+-------------+-------------+------+-----+---------+-----------------------------+
| Field       | Type        | Null | Key | Default | Extra                       |
+-------------+-------------+------+-----+---------+-----------------------------+
| id          | int(11)     | NO   | PRI | NULL    |                             |
| create_time | timestamp   | YES  |     | NULL    | on update CURRENT_TIMESTAMP |
| name        | varchar(20) | YES  |     | NULL    |                             |
+-------------+-------------+------+-----+---------+-----------------------------+
3 rows in set (0.00 sec)

mysql> insert into sharding_month(id,create_time ,name ) values (1,'2018-03-01',database());
Query OK, 1 row affected (0.02 sec)

mysql> insert into sharding_month(id,create_time ,name ) values (2,'2018-04-01',database());
Query OK, 1 row affected (0.00 sec)

mysql> insert into sharding_month(id,create_time ,name ) values (3,'2018-05-01',database());  
Query OK, 1 row affected (0.00 sec)

mysql> insert into sharding_month(id,create_time ,name ) values (4,'2018-05-31',database()); 
Query OK, 1 row affected (0.02 sec)

mysql> insert into sharding_month(id,create_time ,name ) values (5,'2018-06-1',database());   
Query OK, 1 row affected (0.01 sec)

mysql> insert into sharding_month(id,create_time ,name ) values (5,'2018-07-1',database()); 
Query OK, 1 row affected (0.01 sec)

mysql> select * from sharding_month;
+----+---------------------+------+
| id | create_time         | name |
+----+---------------------+------+
|  1 | 2018-03-01 00:00:00 | db1  |
|  5 | 2018-06-01 00:00:00 | db1  |
|  2 | 2018-04-01 00:00:00 | db2  |
|  5 | 2018-07-01 00:00:00 | db2  |
|  3 | 2018-05-01 00:00:00 | db3  |
|  4 | 2018-05-31 00:00:00 | db3  |
+----+---------------------+------+

如果设置了sEndDate,则超过的时间会循环插入各个datanode,如果不设置sEndDate ,则会报错如下。

mysql> insert into sharding_month(id,create_time ,name ) values (6,'2018-08-1',database());
ERROR 1064 (HY000): Can't find a valid data node for specified node index :SHARDING_MONTH -> CREATE_TIME -> 2018-08-1 -> Index : 5

 一致性hash 分片

有效解决了分布式数据扩容问题,后续有数据迁移实践。

schema.xml

<schema name="TESTDB" checkSQLschema="false" sqlMaxLimit="100" dataNode="dn1">
<table name="murmur_hash" primaryKey="ID" dataNode="dn1,dn2,dn3" rule="sharding-by-murmur" /> </schema>

rule.xml

<tableRule name="sharding-by-murmur">
        <rule>
                <columns>id</columns>
                <algorithm>murmur</algorithm>
        </rule>
</tableRule>

        <function name="murmur"
                class="io.mycat.route.function.PartitionByMurmurHash">
                <property name="seed">0</property><!-- 默认是0 -->
                <property name="count">3</property><!-- 要分片的数据库节点数量,必须指定,否则没法分片 -->
                <property name="virtualBucketTimes">160</property><!-- 一个实际的数据库节点被映射为这么多虚拟节点,默认是160倍,也就是
虚拟节点数是物理节点数的160倍 -->
        </function>

登录8066 测试验证

mysql> create table murmur_hash (id int primary key ,name varchar(20));
Query OK, 0 rows affected (0.19 sec)

mysql> insert into murmur_hash(id,name) values (1,database());
Query OK, 1 row affected (0.04 sec)

mysql> insert into murmur_hash(id,name) values (2,database()); 
Query OK, 1 row affected (0.02 sec)

mysql> insert into murmur_hash(id,name) values (3,database()); 
Query OK, 1 row affected (0.00 sec)

mysql> insert into murmur_hash(id,name) values (4,database()); 
Query OK, 1 row affected (0.00 sec)

mysql> insert into murmur_hash(id,name) values (5,database()); 
Query OK, 1 row affected (0.00 sec)

mysql> insert into murmur_hash(id,name) values (6,database()); 
Query OK, 1 row affected (0.00 sec)

mysql> insert into murmur_hash(id,name) values (7,database()); 
Query OK, 1 row affected (0.00 sec)

mysql> insert into murmur_hash(id,name) values (8,database()); 
Query OK, 1 row affected (0.03 sec)

mysql> insert into murmur_hash(id,name) values (9,database()); 
Query OK, 1 row affected (0.00 sec)

mysql> insert into murmur_hash(id,name) values (10,database()); 
Query OK, 1 row affected (0.02 sec)

mysql> insert into murmur_hash(id,name) values (101221,database());
Query OK, 1 row affected (0.03 sec)

mysql> select * from murmur_hash;
+--------+------+
| id     | name |
+--------+------+
|      1 | db2  |
|      2 | db2  |
|      3 | db2  |
|      5 | db1  |
|      6 | db1  |
|      8 | db1  |
|      9 | db2  |
|     10 | db2  |
| 101221 | db2  |
|      4 | db3  |
|      7 | db3  |
+--------+------+

取模分片

schema.xml

<schema name="TESTDB" checkSQLschema="false" sqlMaxLimit="100" dataNode="dn1">

        <table name="part_mod" primaryKey="ID" dataNode="dn1,dn2,dn3"
                   rule="mod-long" />

</schema>

rule.xml

<tableRule name="mod-long">
        <rule>
                <columns>id</columns>
                <algorithm>mod-long</algorithm>
        </rule>
</tableRule>

<function name="mod-long" class="io.mycat.route.function.PartitionByMod">
        <!-- how many data nodes -->
        <property name="count">3</property>
</function>

登录8066 测试验证

mysql> create table part_mod (id int primary key ,name varchar(20));
Query OK, 0 rows affected (0.08 sec)

mysql> desc part_mod;
+-------+-------------+------+-----+---------+-------+
| Field | Type        | Null | Key | Default | Extra |
+-------+-------------+------+-----+---------+-------+
| id    | int(11)     | NO   | PRI | NULL    |       |
| name  | varchar(20) | YES  |     | NULL    |       |
+-------+-------------+------+-----+---------+-------+
2 rows in set (0.00 sec)

mysql> insert into part_mod (id,name) values (1,database());
Query OK, 1 row affected (0.04 sec)

mysql> insert into part_mod (id,name) values (2,database()); 
Query OK, 1 row affected (0.05 sec)

mysql> insert into part_mod (id,name) values (3,database()); 
Query OK, 1 row affected (0.00 sec)

mysql> insert into part_mod (id,name) values (4,database()); 
Query OK, 1 row affected (0.03 sec)

mysql> insert into part_mod (id,name) values (5,database()); 
Query OK, 1 row affected (0.01 sec)

mysql> insert into part_mod (id,name) values (105,database());
Query OK, 1 row affected (0.00 sec)

mysql> select * from part_mod;
+-----+------+
| id  | name |
+-----+------+
|   1 | db2  |
|   4 | db2  |
|   2 | db3  |
|   5 | db3  |
|   3 | db1  |
| 105 | db1  |
+-----+------+
6 rows in set (0.00 sec)

 

posted @ 2018-03-30 20:47  Sin-是我的海  阅读(86)  评论(0)    收藏  举报