Mycat分片(分庫分表)實踐:一張邏輯表拆分爲4臺服務器的16張表

需求

一張業務表有10億數據,需要按身份證號字段certno拆分爲4臺服務器中的16個子表,怎麼操作?

設計

使用mycat的分片功能實現分庫分表

4臺服務器,每臺服務器起一個mysql實例,每個實例創建4個database,每個database建一張同名(tu_trade_ng)的表

制定mycat的分片規則,按certno字段的hash值進行分片

mysql 實例 database tablename
127.0.0.1:7006 nifa_db_t0 tu_trade_ng
nifa_db_t1 tu_trade_ng
nifa_db_t2 tu_trade_ng
nifa_db_t3 tu_trade_ng
127.0.0.1:7007 nifa_db_t0 tu_trade_ng
nifa_db_t1 tu_trade_ng
nifa_db_t2 tu_trade_ng
nifa_db_t3 tu_trade_ng
127.0.0.1:7008 nifa_db_t0 tu_trade_ng
nifa_db_t1 tu_trade_ng
nifa_db_t2 tu_trade_ng
nifa_db_t3 tu_trade_ng
127.0.0.1:7009 nifa_db_t0 tu_trade_ng
nifa_db_t1 tu_trade_ng
nifa_db_t2 tu_trade_ng
nifa_db_t3 tu_trade_ng

實現

mysql創建database

每個mysql實例中創建4個database,共計16個database:

CREATE DATABASE `nifa_db_t0` /*!40100 DEFAULT CHARACTER SET utf8 */;
CREATE DATABASE `nifa_db_t1` /*!40100 DEFAULT CHARACTER SET utf8 */;
CREATE DATABASE `nifa_db_t2` /*!40100 DEFAULT CHARACTER SET utf8 */;
CREATE DATABASE `nifa_db_t3` /*!40100 DEFAULT CHARACTER SET utf8 */;

mysql創建table

每個database中創建一個table,共計16個table:

# 複用了tu_trade_total_area_0的表結構
create table nifa_db_t0.tu_trade_ng like tu_trade_total_area_0;
create table nifa_db_t1.tu_trade_ng like tu_trade_total_area_0;
create table nifa_db_t2.tu_trade_ng like tu_trade_total_area_0;
create table nifa_db_t3.tu_trade_ng like tu_trade_total_area_0;

mycat制定

mycat需要配置的東西:
scheme.xml

<!-- 表名登記 以及分片規則、datanode關聯 -->
<table name="tu_trade_ng" primaryKey="ID"  rule="certno-hashcode"  dataNode="dnng$1-16" />
<!-- 16個datanode -->
<dataNode name="dn1" dataHost="NIFADB_1" database="nifa_db_t0" />
<dataNode name="dn2" dataHost="NIFADB_1" database="nifa_db_t1" />
<dataNode name="dn3" dataHost="NIFADB_1" database="nifa_db_t2" />
<dataNode name="dn4" dataHost="NIFADB_1" database="nifa_db_t3" />
<dataNode name="dn5" dataHost="NIFADB_2" database="nifa_db_t0" />
<dataNode name="dn6" dataHost="NIFADB_2" database="nifa_db_t1" />
<dataNode name="dn7" dataHost="NIFADB_2" database="nifa_db_t2" />
<dataNode name="dn8" dataHost="NIFADB_2" database="nifa_db_t3" />
<dataNode name="dn9" dataHost="NIFADB_3" database="nifa_db_t0" />
<dataNode name="dn10" dataHost="NIFADB_3" database="nifa_db_t1" />
<dataNode name="dn11" dataHost="NIFADB_3" database="nifa_db_t2" />
<dataNode name="dn12" dataHost="NIFADB_3" database="nifa_db_t3" />
<dataNode name="dn13" dataHost="NIFADB_4" database="nifa_db_t0" />
<dataNode name="dn14" dataHost="NIFADB_4" database="nifa_db_t1" />
<dataNode name="dn15" dataHost="NIFADB_4" database="nifa_db_t2" />
<dataNode name="dn16" dataHost="NIFADB_4" database="nifa_db_t3" />
<!-- 4個mysql實例 -->
<dataHost name="NIFADB_1" maxCon="1000" minCon="10" balance="0"
        writeType="0" dbType="mysql" dbDriver="native" switchType="1"  slaveThreshold="100">
        <heartbeat>show slave status</heartbeat>
        <writeHost host="NIFADB_HOST_M1" url="127.0.0.1:7006" user="dusername" password="password">
        </writeHost>
</dataHost>
<dataHost name="NIFADB_2" maxCon="1000" minCon="10" balance="1"
        writeType="0" dbType="mysql" dbDriver="native" switchType="1"  slaveThreshold="100">
        <heartbeat>show slave status</heartbeat>
        <writeHost host="NIFADB_HOST_M2" url="127.0.0.1:7007" user="dusername" password="password">
        </writeHost>
</dataHost>
<dataHost name="NIFADB_3" maxCon="1000" minCon="10" balance="1"
        writeType="0" dbType="mysql" dbDriver="native" switchType="1"  slaveThreshold="100">
        <heartbeat>show slave status</heartbeat>
        <writeHost host="NIFADB_HOST_M3" url="127.0.0.1:7008" user="dusername" password="password">
        </writeHost>
</dataHost>
<dataHost name="NIFADB_4" maxCon="1000" minCon="10" balance="1"
        writeType="0" dbType="mysql" dbDriver="native" switchType="1"  slaveThreshold="100">
        <heartbeat>show slave status</heartbeat>
        <writeHost host="NIFADB_HOST_M4" url="127.0.0.1:7009" user="dusername" password="password">
        < /writeHost>
</dataHost>

rule.xml

<!-- 分片規則 columns是table中的列名 algorithm是分片算法  -->
<tableRule name="certno-hashcode">
    <rule>
        <columns>certno</columns>
        <algorithm>func_ng</algorithm>
    </rule>
</tableRule>
<!-- 分片算法 partitionCount是我們要分的16個表 partitionCount*partitionLength=1024  -->
<!-- 注意1024是固定值,不能變!!!  -->
<function name="func_ng" class="org.opencloudb.route.function.PartitionByLong">
    <property name="partitionCount">16</property>
    <property name="partitionLength">64</property>
</function>

說明:
使用mycat的固定分片hash 算法,本條規則類似於十進制的求模運算,區別在於是二進制的操作,是取id 的二進制低10 位,即id 二進制&1111111111。
此算法的優點在於如果按照10 進製取模運算,在連續插入1-10 時候1-10 會被分到1-10 個分片,增大了插入的事務控制難度,而此算法根據二進制則可能會分到連續的分片,減少插入事務事務控制難度。
1024是固定的,即最大支持1024 分區。

測試

# 插入121條數據 分了五個不等分的批次插入,插入10條到30條不等,每一條的certno字段都不一樣(每批次的certno在數字上連續)
insert into tu_trade_ng (NAME , CERTTYPE , CERTNO , ...... ) values ('餘崇天','0','110120199901012233',......);

# count總的數據量
select count(*) from tu_trade_ng;
+--------+
| COUNT0 |
+--------+
|    121 |
+--------+

# count每個table的數據量 
+-----------+
| count(* ) |
+-----------+
|        60 | // dn1
|         1 | // dn2
|         0 | // dn3
|         0 | // dn4
|         1 | // dn5
|         0 | // dn6
|         0 | // dn7
|         0 | // dn8
|         1 | // dn9
|         1 | // dn10
|         9 | // dn11
|         0 | // dn12
|         1 | // dn13
|         2 | // dn14
|        25 | // dn15
|        20 | // dn16
+-----------+

測試說明了:

  1. 我們的分庫分表生效了,從mycat中查詢的數據量等於從mysql中分表查詢的數據量
  2. 固定分片hash 算法的優點:算法根據二進制則可能會分到連續的分片,減少插入事務事務控制難度

注意

mycat不支持insert into ... select ...這種sql:

insert into tu_trade_ng (NAME , CERTTYPE , CERTNO , ......) 
select NAME , CERTTYPE , CERTNO , ......  from an_old_table;

注意schema中的mysql實例賬號(下面的user字段),要保證該賬號能訪問每一個tu_trade_ng表,不然使用mycat操作的tu_trade_ng會失敗:

<writeHost host="NIFADB_HOST_M3" url="127.0.0.1:7008" user="dusername" password="password">

以上實踐參考官方文檔。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章