1. 程式人生 > >MyCat分片規則(全域性表,ER分片表,多對多關聯,主鍵分片VS非主鍵分片),MyCat常用的分片規則(15中分片規則),自定義MyCat分片規則

MyCat分片規則(全域性表,ER分片表,多對多關聯,主鍵分片VS非主鍵分片),MyCat常用的分片規則(15中分片規則),自定義MyCat分片規則

1 MyCat分片規則

資料切分中重要的幾條原則,其中有幾條資料冗餘,表分組(Table Group)。

1.1全域性表

如果你的業務中有些資料類似於資料字典,比如配置檔案的配置,常用業務的配置或資料量不是很大,很少變動的表,這些表往往不是特別大,而且大部分的業務場景都會用到,那麼這種表適合於MyCat全域性表,無須對資料進行切分。只要在所有的分片上儲存一份資料即可,MyCat在Join操作中,業務表與全域性表進行Join聚合會優先選擇相同分片內的全域性表join,避免跨庫Join,在進行資料插入操作時,mycat 將把資料分發到全域性表對應的 所有分片執行,在進行資料讀取時候將會隨機獲取一個節點讀取資料。

全域性表的配置如下:

<table name=”t_area” primaryKey=”id” type=”gloab” dataNode=”dn1,dn2”/>
  • 1

1.2.ER分片表

有一類業務,例如訂單(order)跟訂單明細(order_detail),明細表會依賴於訂單,也就是說會存在表的主從關係,這類似業務的切分可以抽象出合適的切分規則,比如根據使用者ID切分,其它相關的表都依賴於使用者ID,再或者根據訂單ID切分,總之部分業務總會可以抽象出父子關係的表。這類表適用於ER分片表,子表的記錄與所有關聯的父表記錄存放在同一個資料分片上,避免資料Join跨庫操作。 以order與order_detail例子為例,schema.xml中定義如下的分片配置,order,order_detail根據order_id進行資料切分,保證相同order_id的資料分到同一分片上,在進行資料插入操作時,MyCat會獲取order所在的分片,然後將order_detail也插入到order所在的分片。

<table name=”order” dataNode=”dn$1-32” rule=”mod-long”>
    <childTable name="order_detail" primaryKey="id" joinKey=”order_id” parentKey=”order_id”/>
</table>
  • 1
  • 2
  • 3

1.3.多對多關聯(Mycat弱項)

有一類業務場景是”主表A + 關係表 + 主表B”,舉例來說就是商戶會員 + 訂單 + 商戶,對應這類業務,如果切分: 從會員的角度,如果需要查詢會員購買的訂單,那按照會員進行切分即可,但是如果查詢商戶當天售出的訂單,那又需要按照商戶做切分,可以是如果按照會員又要按照商戶切分,幾乎是無法實現,這類業務如何選擇切分規則非常難。目前還暫時無法很好支援這種模式下的3個表之間的關聯。目前總的原則是需要從業務角度來看,關係表更偏向哪個表,即”A的關係”還是”B的關係”,來決定關係表跟從那個方向來儲存,未來MyCat版本中將考慮將中間表進行雙向複製,以實現從A-關係表以及B-關係表的雙向關聯查詢如下圖所示:這裡寫圖片描述

1.4.主鍵分片vs非主鍵分片

當你沒有任何欄位可以作為分片欄位的時候,主鍵分片就是唯一選擇,其優點是按照主鍵的查詢最快,當採用自動增長的序號作為主鍵時,還能比較均勻的將資料分片在不同的節點上。 若有某個合適的業務欄位比較適合作為分片欄位,則建議採用此業務欄位分片,選擇分片欄位的條件如下: 1、 儘可能的比較均勻分佈資料到各個節點上。 2、 該業務欄位是最頻繁的或者最重要的查詢條件。 常見的除了主鍵之外的其他可能分片欄位有”訂單建立時間”、”店鋪類別”或”所在省”等。當你找到某個合適的業務欄位作為分片欄位以後,不必糾結於”犧牲了按主鍵查詢記錄的效能”,因為在這種情況下,Mycat提供了”主鍵到分片”的記憶體快取機制,熱點資料按照主鍵查詢,絲毫不損失效能。

<table name=”t_user” primaryKey=”user_id” dataNode=”dn$1-32” rule=”mod-long”>
    <childTable name= "t_user_detail" primaryKey=”id” joinKey=”user_id” parentKey=”user_id”/>
</table>
  • 1
  • 2
  • 3

對於非主鍵分片的table,填寫屬性primaryKey,此時MyCat會將你根據主鍵查詢的SQL語句的第一次執行結果進行分析,確定該Table的某個主鍵在什麼分片上,並進行主鍵到分片ID的快取。第二次或後續查詢mycat會優先從快取中查詢是否有idnode即主鍵到分片的對映,如果有直接查詢,通過此種方法提高了非主鍵分片的查詢效能。

2 MyCat常用的分片規則

2.1.分片列舉

通過在配置檔案中配置可能的列舉id,自己的配置分片,本規則適用於特定的場景,比如有些業務需要按照省 份或區縣來做儲存,而全國省份區縣固定的,這類業務使用本條規則,配置如下:

<tableRule name=”sharding-by-intfile”>
<rule>
    <columns>user_id</columns>
    <algorithm>hash-int</algorithm>
</rule>
</tableRule>
<function name=”hash-int” class=”org.opencloudb.route.function.PartitionByFileMap”>
<property name=”mapFile”>partition-hash-int.txt</property>
<property name=”type”>0</property>
<property name=”defaultNode”>0</property>
</function>

partition-hash-int.txt 配置:
10000=0
10010=1
DEFAULT_NODE=1
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

上面columns標識將要分片的表字段,algorithm分片函式。 其中分片函式配置中,mapFile標識配置檔名稱,type預設值為0,0表示Integer,非零表示String,所有的節點配置都是從0開始,以及0代表節點1。

/**
 *defaultNode預設節點:小於0表示不設定預設節點,大於等於0表示設定預設節點
 *預設節點的作用:列舉分片時,如果碰到不識別的列舉值,就讓它路由到預設節點。
 *如果不配置預設節點(defaultNode值小於0表示不配置預設節點),碰到不識別的枚*舉值就會報錯。
*like this:can’t find datanode for sharding column:column_name val:fffffff
 */
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

2.2.固定分片hash演算法

本條規則類似於十進位制的求模運算,在連續插入1-10時候,1-10會被分到1-10個分片,增大了插入的事務控制難度,而此演算法根據二進位制則可能會分到連續的分片,減少插入事務控制難度。

<tableRule name=”rule1”>
<rule>
    <columns>user_id</columns>
    <algorithm>func1</algorithm>
</rule>
</tableRule>
<function name=”func1” class="org.opencloudb.route.function.PartitionByLong">
<property name=”partitionCount”>2,1</property>
<property name=”partitionLength”>256,512</property>
</function>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

配置說明: 上面 columns 標識將要分片的表字段,algorithm 分片函式,partitionCount 分片個數列表,partitionLength分片範圍列表分割槽長度:預設為最大2^n=1024,即最大支援1024分割槽。 約束: count,length兩個陣列的長度必須是一致的。 1024 = sum((count[i] * length[i])).count和length兩個向量的點積恆等於1024

用法例子: 本例的分割槽策略:希望將資料水平分成3份,前兩份各佔25%,第三份佔50%。(故本利非均勻分割槽)

// |<--------------------------1024----------------------------------->|
// |<------256----->|<------256----->|<--------------512-------------->|
// |     partition0 |     partition1 |            partition2          |
  • 1
  • 2
  • 3

// | 共 2 份,故 count[0]=2 | 共 1 份,故 count[1]=1 | int[] count = new int[] { 2, 1 }; int[] length = new int[] { 256, 512 }; PartitionUtil pu = new PartitionUtil(count, length); //下面程式碼演示分別以offerId欄位或memberId欄位根據上述分割槽策略拆分的分配結果 int DEFAULT_STR_HEAD_LEN = 8; // cobar預設會配置為此值 long offerId = 12345; String memberId = “qiushuo”; //若根據offerId分配,partNo1將等於0,即按照上述分割槽策略,offerId為12345時將會被分配到partition0中 int partNo1 = pu.partition(offerId); //若根據memberId分配,partNo2將等於2,即按照上述分割槽策略,memberId為qiushuo時將會被分到partition2中 int partNo2 = pu.partition(memberId, 0, DEFAULT_STR_HEAD_LEN);

如果需要平均分配設定:平均分為 4 分片,partitionCount*partitionLength=1024

<function name="func1" class="org.opencloudb.route.function.PartitionByLong">
<property name="partitionCount">4</property>
<property name="partitionLength">256</property>
</function>
  • 1
  • 2
  • 3
  • 4

2.3.範圍約定

此分片適用於提前規劃好分片欄位某個範圍屬於哪個分片,

start <= range <= end.
    range start-end ,data node index
K=1000,M=10000. 
  • 1
  • 2
  • 3
<tableRule name="auto-sharding-long">
<rule>
    <columns>user_id</columns>
    <algorithm>rang-long</algorithm>
</rule>
</tableRule>
<function name="rang-long" class="org.opencloudb.route.function.AutoPartitionByLong">
<property name="mapFile">autopartition-long.txt</property>
<property name="defaultNode">0</property>
</function>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

配置說明: 上面 columns 標識將要分片的表字段,algorithm 分片函式, rang-long 函式中 mapFile 代表配置檔案路徑 defaultNode 超過範圍後的預設節點。 所有的節點配置都是從 0 開始,及 0 代表節點 1,此配置非常簡單,即預先制定可能的 id 範圍到某個分片 0-500M=0 500M-1000M=1 1000M-1500M=2 或 0-10000000=0 10000001-20000000=1

2.4.取模

此規則為對分片欄位求模運算
  • 1
<tableRule name="mod-long">
<rule>
<columns>user_id</columns>
<algorithm>mod-long</algorithm>
</rule>
</tableRule>
<function name="mod-long" class="org.opencloudb.route.function.PartitionByMod">
<!-- how many data nodes  -->
<property name="count">3</property>
</function>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

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

2.5.按日期(天)分片

此規則為按天分片

<tableRule name="sharding-by-date">
<rule>
<columns>create_time</columns>
<algorithm>sharding-by-date</algorithm>
</rule>
</tableRule>
<function name="sharding-by-date"
class="org.opencloudb.route.function.PartitionByDate">
<property name="dateFormat">yyyy-MM-dd</property> 
<property name="sBeginDate">2014-01-01</property>
<property name="sEndDate">2014-01-02</property>
<property name="sPartionDay">10</property>
</function>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

配置說明: columns :標識將要分片的表字段 algorithm :分片函式 dateFormat :日期格式 sBeginDate :開始日期 sEndDate:結束日期 sPartionDay :分割槽天數,即預設從開始日期算起,分隔 10 天一個分割槽 如果配置了 sEndDate 則代表資料達到了這個日期的分片後後迴圈從開始分片插入。

Assert.assertEquals(true, 0 == partition.calculate(“2014-01-01”)); 
Assert.assertEquals(true, 0 == partition.calculate(“2014-01-10”)); 
Assert.assertEquals(true, 1 == partition.calculate(“2014-01-11”)); 
Assert.assertEquals(true, 12 == partition.calculate(“2014-05-01”));
  • 1
  • 2
  • 3
  • 4

2.6.取模範圍約束

此種規則是取模運算與範圍約束的結合,主要為了後續資料遷移做準備,即可以自主決定取模後資料的節點分佈。

<tableRule name="sharding-by-pattern">
<rule>
<columns>user_id</columns>
<algorithm>sharding-by-pattern</algorithm>
</rule>
</tableRule>
<function name="sharding-by-pattern"
class="org.opencloudb.route.function.PartitionByPattern">
<property name="patternValue">256</property>
<property name="defaultNode">2</property>
<property name="mapFile">partition-pattern.txt</property>
</function>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

partition-pattern.txt

# id partition range start-end ,data node index
###### first host configuration
1-32=0
33-64=1
121

65-96=2
97-128=3
######## second host configuration
129-160=4
161-192=5
193-224=6
225-256=7
0-0=7
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

配置說明: 上面 columns 標識將要分片的表字段,algorithm 分片函式,patternValue 即求模基數,defaoultNode 預設節點,如果配置了預設,則不會按照求模運算 mapFile 配置檔案路徑 配置檔案中,1-32 即代表 id%256 後分布的範圍,如果在 1-32 則在分割槽 1,其他類推,如果 id 非資料,則 會分配在 defaoultNode 預設節點

String idVal = “0”; 
Assert.assertEquals(true, 7 == autoPartition.calculate(idVal)); 
idVal = “45a”; 
Assert.assertEquals(true, 2 == autoPartition.calculate(idVal));
  • 1
  • 2
  • 3
  • 4

2.7.擷取數字做 hash 求模範圍約束

此種規則類似於取模範圍約束,此規則支援資料符號字母取模。

<tableRule name="sharding-by-prefixpattern">
<rule>
<columns>user_id</columns>
<algorithm>sharding-by-prefixpattern</algorithm>
</rule>
</tableRule>
<function name="sharding-by-pattern"
class="org.opencloudb.route.function.PartitionByPrefixPattern">
<property name="patternValue">256</property>
<property name="prefixLength">5</property>
<property name="mapFile">partition-pattern.txt</property>
</function>

partition-pattern.txt
partition-pattern.txt

# range start-end ,data node index
# ASCII
# 8-57=0-9阿拉伯數字
# 64、[email protected]、A-Z
# 97-122=a-z
###### first host configuration
1-4=0
5-8=1
9-12=2
13-16=3
###### second host configuration
17-20=4
21-24=5
25-28=6
29-32=7
0-0=7
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32

配置說明: 上面 columns 標識將要分片的表字段,algorithm 分片函式,patternValue 即求模基數,prefixLength ASCII 擷取的位數 mapFile 配置檔案路徑 配置檔案中,1-32 即代表 id%256 後分布的範圍,如果在 1-32 則在分割槽 1,其他類推 此種方式類似方式 6 只不過採取的是將列種獲取前 prefixLength 位列所有 ASCII 碼的和進行求模 sum%patternValue ,獲取的值,在範圍內的分片數,

String idVal=“gf89f9a”; 
Assert.assertEquals(true, 0==autoPartition.calculate(idVal)); 
idVal=“8df99a”; 
Assert.assertEquals(true, 4==autoPartition.calculate(idVal)); 
idVal=“8dhdf99a”; 
Assert.assertEquals(true, 3==autoPartition.calculate(idVal));
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

2.8.應用指定

此規則是在執行階段有應用自主決定路由到那個分片。
  • 1
<tableRule name="sharding-by-substring">
<rule>
<columns>user_id</columns>
<algorithm>sharding-by-substring</algorithm>
</rule>
</tableRule>
<function name="sharding-by-substring"
class="org.opencloudb.route.function.PartitionDirectBySubString">
<property name="startIndex">0</property><!-- zero-based -->
<property name="size">2</property>
<property name="partitionCount">8</property>
<property name="defaultPartition">0</property>
</function>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

配置說明: 上面 columns 標識將要分片的表字段,algorithm 分片函式 此方法為直接根據字元子串(必須是數字)計算分割槽號(由應用傳遞引數,顯式指定分割槽號)。 例如 id=05-100000002 在此配置中代表根據 id 中從 startIndex=0,開始,擷取 siz=2 位數字即 05,05 就是獲取的分割槽,如果沒傳預設分配到 defaultPartition

2.9.擷取數字hash解析

此規則是擷取字串中的int數值hash分片。
  • 1
<tableRule name="sharding-by-stringhash">
<rule>
    <columns>user_id</columns>
    <algorithm>sharding-by-stringhash</algorithm>
</rule>
</tableRule>
<function name="sharding-by-stringhash"
class="org.opencloudb.route.function.PartitionByString">
<property name="partitionLength">512</property><!-- zero-based -->
<property name="partitionCount">2</property>
<property name="hashSlice">0:2</property>
</function>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

配置說明: 上面 columns 標識將要分片的表字段,algorithm 分片函式 函式中partitionLength 代表字串 hash 求模基數, partitionCount 分割槽數, hashSlice hash 預算位,即根據子字串中 int 值 hash 運算 hashSlice : 0 means str.length(), -1 means str.length()-1

/** 
* “2” -> (0,2) 
* “1:2” -> (1,2) 
* “1:” -> (1,0) 
* “-1:” -> (-1,0) 
* “:-1” -> (0,-1) 
* “:” -> (0,0) 
*/
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

例子:

String idVal=null;
rule.setPartitionLength("512");
rule.setPartitionCount("2");
rule.init();
rule.setHashSlice("0:2");
// idVal = "0";
// Assert.assertEquals(true, 0 == rule.calculate(idVal));
// idVal = "45a";
// Assert.assertEquals(true, 1 == rule.calculate(idVal));
// last 4
rule = new PartitionByString();
rule.setPartitionLength("512");
rule.setPartitionCount("2");
rule.init();
//last 4 characters
rule.setHashSlice("-4:0");
idVal = "aaaabbb0000";
Assert.assertEquals(true, 0 == rule.calculate(idVal));
idVal = "aaaabbb2359";
Assert.assertEquals(true, 0 == rule.calculate(idVal));
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20

2.10.一致性hash

一致性 hash 預算有效解決了分散式資料的擴容問題。

<tableRule name="sharding-by-murmur">
<rule>
<columns>user_id</columns>
<algorithm>murmur</algorithm>
</rule>
</tableRule>
<function name="murmur" class="org.opencloudb.route.function.PartitionByMurmurHash">
<property name="seed">0</property><!--預設是0-->
<property name="count">2</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>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20

2.11.按單月小時拆分

此規則是單月內按照小時拆分,最小粒度是小時,可以一天最多 24 個分片,最少 1 個分片,一個月完後下月 從頭開始迴圈。 每個月內按照小時拆分,最小粒度是小時,可以一天最多24個分片,一個月完後下月開始迴圈。 每個月月尾,需要手工清理資料。

<tableRule name="sharding-by-hour">
<rule>
<columns>create_time</columns>
<algorithm>sharding-by-hour</algorithm>
</rule>
</tableRule>
<function name="sharding-by-hour"
class="org.opencloudb.route.function.LatestMonthPartion">
<property name="splitOneDay">24</property>
</function>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

配置說明:

columns: 拆分欄位,字串型別(yyyymmddHH)
splitOneDay : 一天切分的分片數
LatestMonthPartion partion = new LatestMonthPartion();
partion.setSplitOneDay(24);
Integer val = partion.calculate("2015020100");
assertTrue(val == 0);
val = partion.calculate("2015020216");
assertTrue(val == 40);
val = partion.calculate("2015022823");
assertTrue(val == 27 * 24 + 23);

Integer[] span = partion.calculateRange("2015020100", "2015022823");
assertTrue(span.length == 27 * 24 + 23 + 1);

assertTrue(span[0] == 0 && span[span.length - 1] == 27 * 24 + 23);
span = partion.calculateRange("2015020100", "2015020123");
assertTrue(span.length == 24);
assertTrue(span[0] == 0 && span[span.length - 1] == 23);
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18

2.12.範圍求模分片

先進行範圍分片計算出分片組,組內再求模 優點可以避免擴容時的資料遷移,又可以一定程度上避免範圍分片的熱點問題 綜合了範圍分片和求模分片的優點,分片組內使用求模可以保證組內資料比較均勻,分片組之間是範圍分片可以兼顧範圍查詢。 最好事先規劃好分片的數量,資料擴容時按分片組擴容,則原有分片組的資料不需要遷移。由於分片組內資料比較均勻,所以分片組內可以避免熱點資料問題。

<tableRule name="auto-sharding-rang-mod">
<rule>
    <columns>id</columns>
    <algorithm>rang-mod</algorithm>
</rule>
</tableRule>
<function name="rang-mod"
class="org.opencloudb.route.function.PartitionByRangeMod">
    <property name="mapFile">partition-range-mod.txt</property>
    <property name="defaultNode">21</property>
</function>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

配置說明: 上面 columns 標識將要分片的表字段,algorithm 分片函式 rang-mod 函式中 mapFile 代表配置檔案路徑 defaultNode 超過範圍後的預設節點順序號,節點從 0 開始。

partition-range-mod.txt range start-end ,data node group size 以下配置一個範圍代表一個分片組,=號後面的數字代表該分片組所擁有的分片的數量。 0-200M=5 //代表有 5 個分片節點

200M1-400M=1
400M1-600M=4
600M1-800M=4
800M1-1000M=6
  • 1
  • 2
  • 3
  • 4

2.13.日期範圍hash分片

思想與範圍求模一致,當由於日期在取模會有資料集中問題,所以改成 hash 方法。 先根據日期分組,再根據時間 hash 使得短期內資料分佈的更均勻

優點可以避免擴容時的資料遷移,又可以一定程度上避免範圍分片的熱點問題 要求日期格式儘量精確些,不然達不到區域性均勻的目的

<tableRule name="rangeDateHash">
<rule>
    <columns>col_date</columns>
    <algorithm>range-date-hash</algorithm>
</rule>
</tableRule>
<function name="range-date-hash"
class="org.opencloudb.route.function.PartitionByRangeDateHash">
    <property name="sBeginDate">2014-01-01 00:00:00</property>
    <property name="sPartionDay">3</property>
    <property name="dateFormat">yyyy-MM-dd HH:mm:ss</property>
    <property name="groupPartionSize">6</property>
</function>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
sPartionDay  代表多少天分一個分片
groupPartionSize  代表分片組的大小
  • 1
  • 2

2.14.冷熱資料分片

根據日期查詢日誌資料 冷熱資料分佈 ,最近 n 個月的到實時交易庫查詢,超過 n 個月的按照 m 天分片。

<tableRule name="sharding-by-date"> 
      <rule> 
        <columns>create_time</columns> 
        <algorithm>sharding-by-hotdate</algorithm> 
      </rule> 
   </tableRule>   
<function name="sharding-by-hotdate" class="org.opencloudb.route.function.PartitionByHotDate"> 
    <property name="dateFormat">yyyy-MM-dd</property> 
    <property name="sLastDay">10</property> 
    <property name="sPartionDay">30</property> 
</function>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

2.15.自然月分片

按月份列分割槽 ,每個自然月一個分片,格式 between 操作解析的範例。

<tableRule name="sharding-by-month">
<rule>
<columns>create_time</columns>
<algorithm>sharding-by-month</algorithm>
</rule>
</tableRule>
<function name="sharding-by-month"
class="org.opencloudb.route.function.PartitionByMonth">
<property name="dateFormat">yyyy-MM-dd</property>
<property name="sBeginDate">2014-01-01</property>
</function>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

配置說明: columns: 分片欄位,字串型別 dateFormat : 日期字串格式 sBeginDate : 開始日期

PartitionByMonth partition = new PartitionByMonth();
partition.setDateFormat("yyyy-MM-dd");
partition.setsBeginDate("2014-01-01");
partition.init();
Assert.assertEquals(true, 0 == partition.calculate("2014-01-01"));
Assert.assertEquals(true, 0 == partition.calculate("2014-01-10"));
Assert.assertEquals(true, 0 == partition.calculate("2014-01-31"));
Assert.assertEquals(true, 1 == partition.calculate("2014-02-01"));
Assert.assertEquals(true, 1 == partition.calculate("2014-02-28"));
Assert.assertEquals(true, 2 == partition.calculate("2014-03-1"));
Assert.assertEquals(true, 11 == partition.calculate("2014-12-31"));
Assert.assertEquals(true, 12 == partition.calculate("2015-01-31"));
Assert.assertEquals(true, 23 == partition.calculate("2015-12-31"));
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

3 自定義MyCat分片規則

3.1.修改rule.xml中檔案規則的定義

進入安裝的MyCat目錄,新增tableRule:

<!--針對專案做自定義配置-->
<tableRule name="mod50-long">
<rule>
<columns>id</columns>
        <algorithm>mod50-long</algorithm>
    </rule>
</tableRule>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

新增function內容:

<function name="mod50-long" class="io.mycat.route.function.PartitionByMod">
<!-- how many data nodes -->
    <property name="count">50</property>
</function>
  • 1
  • 2
  • 3
  • 4

3.2.修改schema.xml

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

        <schema name="TESTDB" checkSQLschema="false" sqlMaxLimit="100">
              <table name="tb_pos_trade" primaryKey="id" autoIncrement="true" subTables="tb_pos_trade$1-50" dataNode="dn1" rule="mod50-long" />
        </schema>
        <dataNode name="dn1" dataHost="m1" database="db1" />
        <dataNode name="dn2" dataHost="m2" database="db1" />
        <dataHost name="m1" 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="m1" url="bigdata1:3306" user="root" password="123456">
                        <!-- can have multi read hosts -->
                        <readHost host="hostS2" url="bigdata1:3306" user="root" password="123456" />
                </writeHost>
                <!--<writeHost host="hostS1" url="localhost:3316" user="root" password="123456" />-->
        </dataHost>
        <dataHost name="m2" 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="m2" url="bigdata2:3306" user="root" password="123456"></writeHost>
        </dataHost>
</mycat:schema>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23

4 其它術語

4.1.邏輯表

既然有邏輯庫,那麼就會有邏輯表,分散式資料庫中,對應用來說,讀寫資料的表就是邏輯表。邏輯表,可 以是資料切分後,分佈在一個或多個分片庫中,也可以不做資料切分,不分片,只有一個表構成。

4.2.分片表

分片表,是指那些原有的很大資料的表,需要切分到多個數據庫的表,這樣,每個分片都有一部分資料,所 有分片構成了完整的資料。 例如在 mycat 配置中的 t_node 就屬於分片表,資料按照規則被分到 dn1,dn2 兩個分片節點(dataNode) 上。

<table name=”t_node” primaryKey=”vid” autoIncrement=”true” dataNode=”dn1,dn2” rule1></table>
  • 1

4.3.非分片表

一個數據庫中並不是所有的表都很大,某些表是可以不用進行切分的,非分片是相對分片表來說的,就是那 些不需要進行資料切分的表。 如下配置中 t_node,只存在於分片節點(dataNode)dn1 上。

<table name=”t_node” primaryKey=”vid” autoIncrement=”true” dataNode=”dn1”></table>
  • 1

4.4.ER表

關係型資料庫是基於實體關係模型(Entity-Relationship Model)之上,通過其描述了真實世界中事物與關 系,Mycat 中的 ER 表即是來源於此。根據這一思路,提出了基於 E-R 關係的資料分片策略,子表的記錄與所關 聯的父表記錄存放在同一個資料分片上,即子表依賴於父表,通過表分組(Table Group)保證資料 Join 不會跨 庫操作。 表分組(Table Group)是解決跨分片資料 join 的一種很好的思路,也是資料切分規劃的重要一條規則。

4.5.全域性表

一個真實的業務系統中,往往存在大量的類似字典表的表,這些表基本上很少變動,字典表具有以下幾個特 性: • 變動不頻繁 • 資料量總體變化不大 • 資料規模不大,很少有超過數十萬條記錄。 對於這類的表,在分片的情況下,當業務表因為規模而進行分片以後,業務表與這些附屬的字典表之間的關 聯,就成了比較棘手的問題,所以 Mycat 中通過資料冗餘來解決這類表的 join,即所有的分片都有一份資料的拷 貝,所有將字典表或者符合字典表特性的一些表定義為全域性表。 資料冗餘是解決跨分片資料 join 的一種很好的思路,也是資料切分規劃的另外一條重要規則。

4.6關於分散式事務

參考書籍:《分散式資料庫架構及企業實踐-基於Mycat中介軟體》中的第7章。

--------------------- 本文來自 toto1297488504 的CSDN 部落格 ,全文地址請點選:https://blog.csdn.net/tototuzuoquan/article/details/80362892?utm_source=copy