mycat分片操作


mycat位於應用與數據庫的中間層,可以靈活解耦應用與數據庫,后端數據庫可以位於不同的主機上。在mycat中將表分為兩大類;對於數據量小且不需要做數據切片的表,稱之為分片表;對於數據量大到單庫性能,容量不足以支撐,數據通常需要通過水平切分均勻分布到不同的數據庫中的表,稱之為分片表。而中間件最終需要處理的數據是對數據切分,聚合。

上一片博文中,詳細說明了mycat的server.xml, schema.xml, rule.xml配置文件,下面通過具體的實例,來說明分片的用法及類型。

在說明mycat分片類型之前,需要首先正確配置mycat配置文件。

配置server.xml配置文件: 這個文件如果不修改system標簽中的屬性,那么久可以默;這里通過實例來說明一下user標簽!

        <user name="user">
                <property name="password">user</property>
                <property name="schemas">TESTDB</property>
                <property name="readOnly">true</property>
        </user>

#標簽中的shcemas屬性與schemal.xml配置文件中指定的schema標簽的name屬性值相等。在連接mycat客戶端時,使用show databases命令就會看到這個值
server.xml文件中user標簽

配置schema.xml配置文件: 這個文件配置相對比較多,可以有多個schema標簽:

<?xml version="1.0"?>
<!DOCTYPE mycat:schema SYSTEM "schema.dtd">
<mycat:schema xmlns:mycat="http://io.mycat/">

    <schema name="TESTDB" checkSQLschema="false" sqlMaxLimit="100">         #上面提到過的schema標簽
        <!-- auto sharding by id (long) -->
        <table name="employee" dataNode="dn1,dn2" rule="mod-long" />        #要分片的表,dataNode和下面的dataNode標簽中name屬性對應,rule指定分片規則,分片規則定義在rule.xml文件中 

    </schema>
    <!-- <dataNode name="dn1$0-743" dataHost="localhost1" database="db$0-743"
        /> -->
    <dataNode name="dn1" dataHost="backup-one" database="mytest" />         #分片服務器,一個服務器上可以放多個分片;這里是一個服務器防止一個分片,dataHost屬性指向真正的后端服務器,database指定表在后端服務器上的schema
    <dataNode name="dn2" dataHost="backup-two" database="mytest" />

    <dataHost name="backup-one" maxCon="1000" minCon="10" balance="0"       #dataHost標簽:指定后端真實服務器,由name屬性的值可以被dataNode引用      
              writeType="0" dbType="mysql" dbDriver="native" switchType="1"  slaveThreshold="100">
        <heartbeat>select user()</heartbeat>                                #這個語句用於初始化每個服務器的連接,在主從配置的時候語句會不一樣。
        <writeHost host="hostS1" url="10.0.102.222:3306" user="root"
                   password="123456" />
        </dataHost>

    <dataHost name="backup-two" maxCon="1000" minCon="10" balance="0"
              writeType="0" dbType="mysql" dbDriver="native" switchType="1"  slaveThreshold="100">
        <heartbeat>select user()</heartbeat>
        <writeHost host="hostS1" url="10.0.102.221:3306" user="root"
                   password="123456" />
        </dataHost>
       <!--
    <dataHost name="localhost1" maxCon="1000" minCon="10" balance="0"         #dataHost里面是一個類似於主從的架構,但是可以像上面那樣只配置一個服務器
              writeType="0" dbType="mysql" dbDriver="native" switchType="1"  slaveThreshold="100">
        <heartbeat>select user()</heartbeat>
        <writeHost host="hostM1" url="localhost:3306" user="root"
                   password="123456">
            <readHost host="hostS2" url="192.168.1.200:3306" user="root" password="xxx" />
        </writeHost>
        <writeHost host="hostS1" url="localhost:3316" user="root"
                   password="123456" />
    </dataHost> -->

</mycat:schema>

rule.xml: 主要是分片規則和分片鍵的定義,會在具體分片類型的時候說明。

首先我們要在真實的服務器上,對應的schema中創建測試庫:

mysql> CREATE table employee(id int, name varchar(30));
Query OK, 0 rows affected (0.05 sec)

#連接mycat客戶端
[root@test1 conf]# mysql -uroot -P8066 -h127.0.0.1
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 5
Server version: 5.6.29-mycat-1.6-RELEASE-20161028204710 MyCat Server (OpenCloundDB)

Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql> show databases;
+----------+
| DATABASE |
+----------+
| TESTDB   |
+----------+
1 row in set (0.01 sec)

mysql> use TESTDB;
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A

Database changed
mysql> show tables;
+------------------+
| Tables in TESTDB |
+------------------+
| employee         |
+------------------+
1 row in set (0.00 sec)

mysql> 

 

  • 求模分片: 對分片的字段進行取模處理,配置如下:
            <tableRule name="mod-long">                              #分片規則名稱
                    <rule>
                            <columns>id</columns>                     #進行分片的字段值
                            <algorithm>mod-long</algorithm>           #分片算法,由后面的function標簽指定。  
                    </rule>
            </tableRule>
    
            <function name="mod-long" class="io.mycat.route.function.PartitionByMod">
                    <!-- how many data nodes -->
                    <property name="count">2</property>              # 數據要分成幾分片,這個值不能大於datanode指定的數值,不然會報錯
            </function>

    配置說明:
    上面說明columns標識將要分片的表字段,algorithm標識分片函數。
    此種配置非常明確即根據id進行十進制求模預算,相比固定分片的hash,此種在批量插入時可能存在批量插入單事務插入多數據分
    片,增大事務一致性難度。

    測試:

    #通過mycat客戶端插入數據,
    mysql> insert into employee(id, name) values(1,"a"); Query OK, 1 row affected (0.02 sec) mysql> insert into employee(id, name) values(2,"b"); Query OK, 1 row affected (0.01 sec) mysql> insert into employee(id, name) values(3,"c"); Query OK, 1 row affected (0.03 sec) mysql> insert into employee(id, name) values(4,"d"); Query OK, 1 row affected (0.01 sec) mysql> insert into employee(id, name) values(5,"e"); Query OK, 1 row affected (0.01 sec) mysql> insert into employee(id, name) values(6,"f"); Query OK, 1 row affected (0.01 sec) #上面的6條數據會分以字段id的值為分片鍵,因為分片基數為2,所以數據分奇數,偶數分別存儲到對應的服務器上。【id的值除以2取模,模的數值對應着對應的服務器】 mysql> show @@datasource; +----------+--------+-------+--------------+------+------+--------+------+------+---------+-----------+------------+ | DATANODE | NAME | TYPE | HOST | PORT | W/R | ACTIVE | IDLE | SIZE | EXECUTE | READ_LOAD | WRITE_LOAD | +----------+--------+-------+--------------+------+------+--------+------+------+---------+-----------+------------+ | dn2 | hostS1 | mysql | 10.0.102.221 | 3306 | W | 0 | 10 | 1000 | 438 | 3 | 3 | | dn1 | hostS1 | mysql | 10.0.102.222 | 3306 | W | 0 | 10 | 1000 | 444 | 8 | 3 | +----------+--------+-------+--------------+------+------+--------+------+------+---------+-----------+------------+ 2 rows in set (0.01 sec)

     

  • 枚舉分片: 通過配置文件中配置可能的枚舉id,自己配置分片,本規則適用於特定的場景,比如有些業務需要按照省份或區縣來保存,而全國省份是固定的,這類業務可以使用本條規則。配置如下:
            <tableRule name="sharding-by-intfile">         
                    <rule>
                            <columns>name</columns>               #枚舉分片字段
                            <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>                                 #值為0表示的是整型,非0表示string
            </function>

    #查看partition-hash-int.txt文件,文件就在當前配置文件目錄下面
    [root@test1 conf]# cat partition-hash-int.txt
    zhao=0 #如果name的值為“zhao”則分片到第一個服務器
    qian=1

    #
    插入數據測試
    mysql> insert into employee(id, name) values(1,"zhao");
    Query OK, 1 row affected (0.06 sec)

    mysql> insert into employee(id, name) values(2,"qian");
    Query OK, 1 row affected (0.01 sec)

    mysql> insert into employee(id, name) values(3,"wang"); #如果插入的值在映射文件中沒有對應的映射則會報錯,因此需要一個參數來配置默認的存儲位置。
    ERROR 1064 (HY000): can't find any valid datanode :EMPLOYEE -> NAME -> wang


    <property name="defaultNode">1</property> #表示默認的配置文件,當插入的值在映射中找不到時就會插入到這個服務上。對應的映射配置文件如下
    [root@test1 conf]# cat partition-hash-int.txt 
    zhao=0
    qian=1
    DEFAULT_NODE=1

     

  • 范圍分片,適用於想明確知道某個范圍屬於哪個分片。
    #第一修改schema.xml中的分片規則
    <table name="employee" dataNode="dn1,dn2" rule="auto-sharding-long" />
    #范圍分片的rule文件不用修改,如下
        <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>    #指定映射文件的路徑
            <property name="defaultNode">0</property>             #默認分片
        </function>
    
    #查看autopartition-long.txt文件
    [root@test1 conf]# cat autopartition-long.txt 
    # range start-end ,data node index
    # K=1000,M=10000.                    #在這個文件中,K表示1000, M表示10000.
    0-500=0                              #0~500,分入第一個分片
    500-1000=1                           #500~1000, 分入第二個分片

    測試數據:

    #連接mycat客戶端,插入測試數據
    mysql> insert into employee(id, name) values(1,"a"),(501,"b");
    Query OK, 2 rows affected (0.01 sec)
    
    mysql> insert into employee(id, name) values(2,"a"),(502,"b");
    Query OK, 2 rows affected (0.01 sec)
    #連接到對應的mysql服務器查看,數據
    [root@test1 conf]# mysql -uroot -p123456 -h10.0.102.222 -e "select * from mytest.employee"
    mysql: [Warning] Using a password on the command line interface can be insecure.
    +------+------+
    | id   | name |
    +------+------+
    |    1 | a    |
    |    2 | a    |
    +------+------+
    [root@test1 conf]# mysql -uroot -p123456 -h10.0.102.221 -e "select * from mytest.employee"
    mysql: [Warning] Using a password on the command line interface can be insecure.
    +------+------+
    | id   | name |
    +------+------+
    |  501 | b    |
    |  502 | b    |
    +------+------+
    [root@test1 conf]# 
  • 范圍求模算法: 該算法為先進行范圍分片,計算出分片組,組內再求模,綜合了范圍分片和求模分片的優點。分片組內使用求模可以保證組內的數據分布比較均勻,分片組之間采用范圍分片可以兼顧范圍分片的特點。事先規定好分片的數量,數據擴容時按分片組擴容,則原有分片組的數據不需要遷移。由於分片組內的數據分布比較均勻,所以分片組內可以避免熱點數據問題。
    #注意修改schema.xml中分片算法名字       
    <tableRule name="auto-sharding-long"> <rule> <columns>id</columns> <algorithm>rang-long</algorithm> </rule> </tableRule> <function name="rang-mod" class="io.mycat.route.function.PartitionByRangeMod"> <property name="mapFile">partition-range-mod.txt</property> <property name="defaultNode">2</property> </function> #查看映射文件的數值 [root@test1 conf]# cat partition-range-mod.txt # range start-end ,data node group size 0-200M=5 #id取值在這個范圍的有5個分片節點 200M1-400M=1 400M1-600M=4 600M1-800M=4 800M1-1000M=6

    #這個分片算法需要的分片節點相對比較多,因此沒有測試!首先根據id進行分組,然后再組內根據id的值進行取模求值,確定該記錄究竟存在組內的哪一個節點上。
    #后續補上測試數據。

     

  • 固定分片哈希算法:本條規則類似於十進制的求模運算,區別在於是二進制的操作,是取id的二進制低10位,即id二進制&1111111111.此算法的優點在於如果按照10進制取模運算,在連續插入1-10時候1-10會被分到1-10個分片,增大了插入的事務控制難度,而此算法根據二進制則可能會分到連續的分片上,減少插入的事務控制難度。為了測試這個分片算法,我們在schema.xml中又添加了一個服務器,限制schema.xml配置文件如下:
            <schema name="TESTDB" checkSQLschema="false" sqlMaxLimit="100">
                    <!-- auto sharding by id (long) -->
                    <table name="employee" dataNode="dn1,dn2,dn3" rule="rule1" />
            </schema>
            <!-- <dataNode name="dn1$0-743" dataHost="localhost1" database="db$0-743"
                    /> -->
            <dataNode name="dn1" dataHost="backup-one" database="mytest" />
            <dataNode name="dn2" dataHost="backup-two" database="mytest" />
            <dataNode name="dn3" dataHost="backup-three" database="mytest" />
            <!--<dataNode name="dn4" dataHost="sequoiadb1" database="SAMPLE" />
            <dataNode name="jdbc_dn3"       dataHost="jdbchost" database="db3" /> -->
            <dataHost name="backup-one" maxCon="1000" minCon="10" balance="0"
                              writeType="0" dbType="mysql" dbDriver="native" switchType="1"  slaveThreshold="100">
                    <heartbeat>select user()</heartbeat>
                    <writeHost host="hostS1" url="10.0.102.222:3306" user="root"
                                       password="123456" />
            </dataHost>
    
            <dataHost name="backup-two" maxCon="1000" minCon="10" balance="0"
                              writeType="0" dbType="mysql" dbDriver="native" switchType="1"  slaveThreshold="100">
                    <heartbeat>select user()</heartbeat>
                    <writeHost host="hostS2" url="10.0.102.221:3306" user="root"
                                       password="123456" />
            </dataHost>
    
            <dataHost name="backup-three" maxCon="1000" minCon="10" balance="0"
                              writeType="0" dbType="mysql" dbDriver="native" switchType="1"  slaveThreshold="100">
                    <heartbeat>select user()</heartbeat>
                    <writeHost host="hostS3" url="10.0.102.204:3306" user="root"
                                       password="123456" />
            </dataHost>
    schema.xml配置文件

    rule配置文件如下:

            <tableRule name="rule1">
                    <rule>
                            <columns>id</columns>
                            <algorithm>func1</algorithm>
                    </rule>
            </tableRule>
    
            <function name="func1" class="io.mycat.route.function.PartitionByLong">
                    <property name="partitionCount">2,1</property>
                    <property name="partitionLength">256,512</property>
            </function>

      partitionCount屬性表示分片的個數。
    partitionLength屬性表示分片范圍列表。
    分區長度默認為1024=2^10,最大長度也就為1024.
    約束條件:
    count,和length兩個數組長度必須是一致的。
    count和length兩個向量的點積恆等於1024.上面的256*2 + 512*1=1024.

    上面的分片把數據水平分為三分,那么究竟怎么分片呢?上面提到了分片鍵數值的二進制與1111111111(10個1)取與值,結果也就是分片鍵的二進制低10位的數值,因為2**10=1024,所以最大支持1024個分區。數據水平分為3分,前面分別為256:256:512。partitionCount取值中所有的分片個數為2+1=3;前2個分區中每個分區的范圍是256,后面一個是512;恰好為1024.測試如下:

    #插入數據,分析數據插入哪個分片時,要使用分片鍵id值的低10位二進制數字。
    mysql> insert into employee(id, name) values(129,"a"),(145,"b"); Query OK, 2 rows affected (0.01 sec) Records: 2 Duplicates: 0 Warnings: 0 mysql> insert into employee(id, name) values(257,"a"),(300,"b"); Query OK, 2 rows affected (0.01 sec) Records: 2 Duplicates: 0 Warnings: 0 mysql> insert into employee(id, name) values(500,"a"),(600,"b"); Query OK, 2 rows affected (0.01 sec) mysql> insert into employee(id, name) values(198,"a"),(734,"b"); Query OK, 2 rows affected (0.03 sec) mysql> insert into employee(id, name) values(1444,"a"),(2345,"b");
    #十進制數1444,二進制表示為100 1010 0100,低10位的二進制數為:00 1010 0100,化為十進制數為420,因此在256~512這個區間。更快的方法是id值除以1024取模,哪個余數多少,就落在對應的空間。
    #1444*1024=1余420 Query OK, 2 rows affected (0.00 sec) Records: 2 Duplicates: 0 Warnings: 0
    #查看數據分布 [root@test1 conf]# mysql -uroot -p123456 -h10.0.102.222 -e "select * from mytest.employee" mysql: [Warning] Using a password on the command line interface can be insecure. +------+------+ | id | name | +------+------+ | 129 | a | | 145 | b | | 198 | a | +------+------+ [root@test1 conf]# mysql -uroot -p123456 -h10.0.102.221 -e "select * from mytest.employee" mysql: [Warning] Using a password on the command line interface can be insecure. +------+------+ | id | name | +------+------+ | 257 | a | | 300 | b | | 500 | a | | 1444 | a | | 2345 | b | +------+------+ [root@test1 conf]# mysql -uroot -p123456 -h10.0.102.204 -e "select * from mytest.employee" mysql: [Warning] Using a password on the command line interface can be insecure. +------+------+ | id | name | +------+------+ | 600 | b | | 734 | b | +------+------+

     

  • 取模范圍算法: 此種規則是取模運算與范圍約束結合,主要為了后續數據遷移做准備,即可以自主決定取模后數據的節點分別。
    #schema.xml中選擇算法
    <table name="employee" dataNode="dn1,dn2,dn3" rule="sharding-by-pattern" />
    
    #這個算法在rule默認文件中並沒有,因此需要自己編寫對應的參數,調用接口即可!
        <tableRule name="sharding-by-pattern">
            <rule>
                <columns>id</columns>
                <algorithm>sharding-by-pattern</algorithm>
            </rule>
        </tableRule>
    
        <function name="sharding-by-pattern"
            class="io.mycat.route.function.PartitionByPattern">
            <property name="mapFile">partition-pattern.txt</property>
            <property name="patternValue">8</property>
            <property name="defaultNode">2</property>
        </function>

    patternValue: 即求模基數

    #這里需要注意tableRule標簽和function標簽不要寫一塊,不然會報錯,【感覺很奇怪,就像這樣寫一塊會報如下錯誤,但是若是分開寫就可以】 The content of element type "mycat:rule" must match "(tableRule*,function*)". #然后編寫映射文件 [root@test1 conf]# cat partition-pattern.txt 0-3=0 4-6=1 7-8=2

    id除以求模基數,得到的余數在0-3之間的分配到第一個節點。依次類推。如果id為非數值類型,則會分配到默認節點。

     

  • 字符串hash求模范圍算法: 與取模范圍算法類似,該算法支持數值,符合,字母取模。
    <table name="employee" dataNode="dn1,dn2,dn3" rule="sharding-by-prefixpattern" />
    
    #rule.xml配置文件如下
        <tableRule name="sharding-by-prefixpattern">
            <rule>
                <columns>name</columns>
                <algorithm>sharding-by-prefixpattern</algorithm>
            </rule>
        </tableRule>
    
        <function name="sharding-by-prefixpattern"
            class="io.mycat.route.function.PartitionByPrefixPattern">
            <property name="mapFile">partition-pattern.txt</property>
            <property name="patternValue">8</property>
            <property name="prefixLength">1</property>
        </function>
    #patternValue為求模基數
    #prefixLength:為截取的位數
    #mapFile為配置文件
    [root@test1 conf]# cat partition-pattern.txt 
    0-3=0
    4-6=1
    7-8=2

    #說明,該算法與取模范圍算法類似,截取長度為prefixLength的子串,再對子串的每個字符的ASCII碼求sum,然后再對sum的值以patternValue為基數求模。
    #這里為了測試方便prefixLength長度設置為了1.

    測試數據如下:

    先插入數據
    mysql> insert into employee(id, name) values(11,"ano");
    Query OK, 1 row affected (0.01 sec)
    
    mysql> insert into employee(id, name) values(12,"eno");
    Query OK, 1 row affected (0.01 sec)
    
    mysql> insert into employee(id, name) values(13,"gno");
    Query OK, 1 row affected (0.03 sec)
    
    #查看插入數據的數據分布
    [root@test1 conf]#  mysql -uroot -p123456 -h10.0.102.204 -e "select * from mytest.employee"
    mysql: [Warning] Using a password on the command line interface can be insecure.
    +------+------+
    | id   | name |
    +------+------+
    |   13 | gno  |
    +------+------+
    [root@test1 conf]#  mysql -uroot -p123456 -h10.0.102.221 -e "select * from mytest.employee"
    mysql: [Warning] Using a password on the command line interface can be insecure.
    +------+------+
    | id   | name |
    +------+------+
    |   12 | eno  |
    +------+------+
    [root@test1 conf]#  mysql -uroot -p123456 -h10.0.102.222 -e "select * from mytest.employee"
    mysql: [Warning] Using a password on the command line interface can be insecure.
    +------+------+
    | id   | name |
    +------+------+
    |   11 | ano  |

     

  • 應用指定算法: 此規則是在運行階段由自主決定路由到那個分片。
     <table name="employee" dataNode="dn1,dn2,dn3" rule="sharding-by-substring" />
    
    #rule.xml配置如下:
            <tableRule name="sharding-by-substring">
                    <rule>
                            <columns>id</columns>
                            <algorithm>sharding-by-substring</algorithm>
                    </rule>
            </tableRule>
    
    
            <function name="sharding-by-substring"
                    class="io.mycat.route.function.PartitionDirectBySubString">
                    <property name="startIndex">0</property>
                    <property name="size">2</property>
                    <property name="partitionCount">3</property>
                    <property name="defautlPartition">0</property>
            </function>
    #直接根據子字串(必須是數字)計算分區號(由應用傳遞函數,顯式指定分區號)。例如id=05-10043,其中分區號是從startindex=0的位置開始截取,然后截取2個字節的數字,
    #即05, 表示第5個分區。

    測試數據:

    #mysql直接插入以0開始的數字,存儲時會自動把0去掉,可以在對應字段上添加zerofill屬性,但是這樣只是在顯示的時候,不夠指定的位數時補上0而已。
    #因此這里把id的屬性由int類型修改為varchar類型,這樣就可以作為字符串存儲了。若是不想修改字符串類型,畢竟如果表特別大,這是一個代價很大的操作。
    #可以修改rule的配置文件,把startIndex修改為不是0開始的,這樣也是可以的。
    mysql> alter table employee modify id varchar(10); Query OK, 3 rows affected (0.16 sec) Records: 0 Duplicates: 0 Warnings: 0 mysql> insert into employee(id, name) values("014354","first"); Query OK, 1 row affected (0.01 sec) mysql> insert into employee(id, name) values("025463","second"); Query OK, 1 row affected (0.03 sec) mysql> insert into employee(id, name) values("039864","third"); Query OK, 1 row affected (0.04 sec) mysql> insert into employee(id, name) values("099864","third"); Query OK, 1 row affected (0.01 sec) [root@test1 conf]# mysql -uroot -p123456 -h10.0.102.222 -e "select * from mytest.employee" mysql: [Warning] Using a password on the command line interface can be insecure. +--------+-------+ | id | name | +--------+-------+ | 039864 | third | +--------+-------+ [root@test1 conf]# mysql -uroot -p123456 -h10.0.102.221 -e "select * from mytest.employee" mysql: [Warning] Using a password on the command line interface can be insecure. +--------+-------+ | id | name | +--------+-------+ | 014354 | first | +--------+-------+ [root@test1 conf]# mysql -uroot -p123456 -h10.0.102.204 -e "select * from mytest.employee" mysql: [Warning] Using a password on the command line interface can be insecure. +--------+--------+ | id | name | +--------+--------+ | 025463 | second | +--------+--------+

     

  • 一致性哈希算法:一致性哈希算法有效的解決了數據的擴容問題。

 

  • 按時間分片:這個按時間分片范圍有點大,mycat支持可以使用按天,按小時,按自然月的分片算法。這里僅通過一個按自然月分片的算法實例,說明其用法。按月分片時:單月內按小時拆分,最小粒度是小時,一天最多可以有24個分片,最少1個分片,下個月從頭開始,每個月末需要手工清理數據。自然月分片使用場景為按月份分區,每個自然月一個分區,查詢條例時使用between and。
    <table name="employee" dataNode="dn1,dn2,dn3" rule="sharding-by-month" />
    
    #rule.xml配置文件
    
            <tableRule name="sharding-by-month">
                    <rule>
                            <columns>id</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-11-01</property>
            </function>
    
    
    
    #dataFormat: 為日期格式
    #sBeginDate: 為開始日期

    測試:

    因為測試只有3個分片,因此上面的哪個開始日期選擇的是距現在3個月的時間。
    在測試之前需要修改表字段類型為date:
    mysql> alter table employee modify id date;
    Query OK, 0 rows affected (0.08 sec)
    Records: 0  Duplicates: 0  Warnings: 0
    
    #插入數據
    mysql> insert into employee(id, name) values("2018-11-23", "fuck");
    Query OK, 1 row affected (0.00 sec)
    
    mysql> insert into employee(id, name) values("2018-12-15", "what a fuck");
    Query OK, 1 row affected (0.01 sec)
    
    mysql> insert into employee(id, name) values("2019-1-16", "yesterday");
    Query OK, 1 row affected (0.03 sec)
    #查看數據
    [root@test1 conf]#  mysql -uroot -p123456 -h10.0.102.221 -e "select * from mytest.employee"
    mysql: [Warning] Using a password on the command line interface can be insecure.
    +------------+-------------+
    | id         | name        |
    +------------+-------------+
    | 2018-12-15 | what a fuck |
    +------------+-------------+
    [root@test1 conf]#  mysql -uroot -p123456 -h10.0.102.222 -e "select * from mytest.employee"
    mysql: [Warning] Using a password on the command line interface can be insecure.
    +------------+------+
    | id         | name |
    +------------+------+
    | 2018-11-23 | fuck |
    +------------+------+
    [root@test1 conf]#  mysql -uroot -p123456 -h10.0.102.204 -e "select * from mytest.employee"
    mysql: [Warning] Using a password on the command line interface can be insecure.
    +------------+-----------+
    | id         | name      |
    +------------+-----------+
    | 2019-01-16 | yesterday |
    +------------+-----------+
    
    #插入一個在分片時間區間之外的時間,會報錯
    mysql> insert into employee(id, name) values("2018-1-16", "yesterday");
    ERROR 1064 (HY000): Can't find a valid data node for specified node index :EMPLOYEE -> ID -> 2018-1-16 -> Index : -10
    mysql> 

     

  • 一致性哈希算法:一致性hash算法有效解決了分布式數據的擴容問題,
    <table name="employee" dataNode="dn1,dn2,dn3" rule="sharding-by-murmur" />
    
    #rule配置文件如下
            <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倍 -->
                    <!-- <property name="weightMapFile">weightMapFile</property> 節點的權重,沒有指定權重的節點默認是1。以properties文件的格式填寫,以從0開始到count-1的整數
    值也就是節點索引為key,以節點權重值為值。所有權重值必須是正整數,否則以1代替 -->
                    <!-- <property name="bucketMapPath">/etc/mycat/bucketMapPath</property> 
                            用於測試時觀察各物理節點與虛擬節點的分布情況,如果指定了這個屬性,會把虛擬節點的murmur hash值與物理節點的映射按行輸出到這個文件,沒有默認值,如>果不指定,就不會輸出任何東西 -->
            </function>

    測試:

    mysql> insert into employee(id, name) values(12,"a");
    Query OK, 1 row affected (0.02 sec)
    
    mysql> insert into employee(id, name) values(34,"b");
    Query OK, 1 row affected (0.01 sec)
    
    mysql> insert into employee(id, name) values(56,"7");
    Query OK, 1 row affected (0.02 sec)
    
    #查看數據
    [root@test1 conf]#  mysql -uroot -p123456 -h10.0.102.204 -e "select * from mytest.employee"
    mysql: [Warning] Using a password on the command line interface can be insecure.
    +------+------+
    | id   | name |
    +------+------+
    |   12 | a    |
    +------+------+
    [root@test1 conf]#  mysql -uroot -p123456 -h10.0.102.222 -e "select * from mytest.employee"
    mysql: [Warning] Using a password on the command line interface can be insecure.
    +------+------+
    | id   | name |
    +------+------+
    |   34 | b    |
    +------+------+
    [root@test1 conf]#  mysql -uroot -p123456 -h10.0.102.221 -e "select * from mytest.employee"
    mysql: [Warning] Using a password on the command line interface can be insecure.
    +------+------+
    | id   | name |
    +------+------+
    |   56 | 7    |
    +------+------+

    網上看到一片博文,說明了一致性hash算法:https://blog.csdn.net/ydyang1126/article/details/70313981

     

  • 字符串hash解析算法【暫時沒有找到資料,網上資料凈抄襲】

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM