【Mycat】分片規則詳解

分片表和非分片表

  1. Mycat位於應用和數據庫的中間層,可以理解爲數據庫的代理。
  2. 不是所有的表都需要分片,數據量小並且不需要做水平切分的表稱之爲非分片表;數據量大到單庫性能、容量不足以支撐,數據需要通過水平切分到不同數據庫中的表稱之爲分片表。

ER關係分片表

  1. ER模型是實體關係模型,廣泛採用概念模型設計方法,基本元素是實體、關係和屬性。Mycat創新性地將它引入數據切分規則中,使得有互相依賴的表能夠按照某一規則切分到相同的節點上,避免跨庫Join關聯查詢。
  2. 以訂單(order)和訂單明細(order_detail)舉例,訂單明細依賴訂單表,存在主從關係。這類表適用於ER分片表,子表的記錄與所關聯的父表記錄存放在同一個數據分片上,避免跨庫Josin操作,分片規則可以按照用戶ID或者訂單ID切分,這個看具體的業務需要。
  3. 以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" />
</table>

分片規則rule.xml文件詳解

rule.xml位於$MYCAT_HOME/conf目錄,它定義了所有拆分表的規則。在使用的時候可以靈活指定需要使用的分片算法,或者對同一個分片算法使用不同的參數。可以理解爲是分片算法的定義文件,這個算法可以用不同的參數重載,在schema.xml中表的rule屬性可以定義所使用的具體算法name。

Function標籤

<function name="rang-mod" class="org.opencloudb.route.function.PartitionByRangeMod">
    <property name="mapFile">partition-range-mod.txt</property>
</function>
  • name屬性指定算法的名稱,在該文件中唯一。
  • class屬性對應具體的分片算法,需要指定算法的具體類。
  • property屬性根據算法的要求指定,後面詳細說明。

tableRule標籤

<tableRule name="auto-sharding-rang-mod">
    <rule>
        <columns>id</coluns>
        <algorithm>rang-mod</algorithm>
    </rule>
</tableRule>
  • name屬性指定分片唯一算法的名稱。
  • rule屬性指定分片算法的具體內容,包括columns和algorithm兩個屬性。
  • columns屬性指定對應的表中用於分片的列名。
  • algorithm屬性對應function中指定的算法名稱。

分片算法詳解

取模分片

<tableRule name="mod-long">
    <rule>
        <columns>id</coluns>
        <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>
  • columns用來標識將要分片的表字段。
  • algorithm指定分片函數與function對應。
    此分片算法根據id進行十進制求模計算,相比固定的分片hash,這種分片算法在批量插入時會增加事務一致性的難度。

枚舉分片

通過在配置文件中配置可能的枚舉id,指定數據分佈到不同物理節點上,本規則適用於按照省份或區縣來拆分數據類業務。

<tableRule name="sharding-by-intfile">
    <rule>
        <columns>sharding_id</coluns>
        <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
  • columns指定分片的表列名。
  • algorithm指定分片函數的名稱,與function中mapFile配置文件標識的名稱一致。
  • type的默認值爲0,0表示Integer,非零表示String。

注意:

  • 所有的節點配置都是從0開始的,0代表節點1
  • defaultNode默認節點:小於0表示不設置默認節點,大於等於0表示設置默認節點
  • 默認節點的作用:枚舉分片時,如果碰到不識別的枚舉值,就讓它路由到默認節點
  • 如果不設置默認節點,則碰到識別不了的枚舉值就會報錯,如:
like this: can`t find datanode for sharding column:column_name val:ffffffff

範圍分片

<tableRule name="auto-sharding-long">
    <rule>
        <columns>id</coluns>
        <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>

autopartition-long.txt的配置如下:

# range start-end, data node index
# K=100,M=10000
0-3000000=0
3000001-4000000=1
4000001-6000000=2
  • columns指定分片的表列名。
  • algorithm指定分片函數和function對應。
  • rang-long函數中的mapFile代表配置文件的路徑。
  • defaultNode爲超出範圍後的默認節點。

所有的節點配置都是從0開始的,0代表節點1,此配置非常簡單,即預先設計好某個分片的id範圍。

範圍求模算法

該算法爲先進行範圍分片,計算出分片組,組內再求模,綜合了範圍分片和求模分片的優點。分片組內使用求模可以保證組內的數據分佈比較均勻,分片組之間採用範圍分片可以兼顧範圍分片的特點。事先規定好分片的數量,數據擴容時按照分片組擴容,則原有分片組的數據不需要遷移。由於分片組內的數據分佈比較均勻,所以分片組內可以避免熱點數據問題。

<tableRule name="auto-sharding-rang-mod">
    <rule>
        <columns>id</coluns>
        <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>

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
  • columns指定分片的表列名。
  • algorithm指定分片函數和function對應。
  • mapFile指定分片的配置文件。
  • 未包含以上規則的數據存儲在defaultNode節點中,節點從0開始。

固定分片hash算法

類似於十進制的求模運算,但是爲二進制的操作,取id的二進制低十位,即id二進制&1111111111。

此算法的優點在於如果按照十進制取模運算,則在連續插入110時,110會被分到1~10個分片中,增大了插入事務的控制難度。而此算法根據二進制則可能會分到連續的分片,降低了插入事務的控制難度。

<tableRule name="rule1">
    <rule>
        <columns>user_id</coluns>
        <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>
  • columns標識將要分片的表字段。
  • algorithm爲分片函數。
  • partitionCount爲分片個數列表
  • partitionLength爲分片範圍列表,分區長度默認最大爲2^n=1024,即最大支持1024個分區。
    約束如下:
  • count、length兩個數組的長度必須一致
  • 1024 = sum(count[i]*length[i]),count和length兩個向量的點積恆等於1024.

取模範圍算法

取模運算與範圍約束的結合主要是爲後續的數據遷移做準備,即可以自主決定取模後數據的節點分佈,配置如下:

<tableRule name="sharding-by-pattern">
    <rule>
        <columns>user_id</coluns>
        <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>

partition-pattern.txt配置如下:

# id partition rage start-end, data node index
###### first host configuration
1-32=0
33-64=1
65-96=2
97-128=3
###### second host configuration
129-160=4
161-192=5
193-224=6
225-256=7
0-0=7
  • columns標識將要分片的表字段。
  • algorithm爲分片函數
  • patternValue爲求模基數。
  • defaultNode爲默認節點,如果採用默認配置,則不會進行求模運算。

在mapFile配置文件中,132即代表id%256後分布的範圍。如果在132,則在分區1,以此類推,如果id不是數據,則會分配在defaultNode上。

字符串hash求模範圍運算

與取模範圍運算類似,該算法支持數值、符號、字母取模,配置如下:

<tableRule name="sharding-by-prefixpattern">
    <rule>
        <columns>user_id</coluns>
        <algorithm>sharding-by-prefixpattern</algorithm>
    </rule>
</tableRule>
<function name="sharding-by-prefixpattern" 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配置如下:

# rage start-end, data node index
# ASCII
8-57=0-9阿拉伯數字
# 64、65-90=@、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
  • columns標識將要分片的表字段。
  • algorithm爲分片函數
  • patternValue爲求模基數。
  • prefixLength爲截取的位數。
  • mapFile爲配置文件。
  • 132代表id%256後分布的範圍,如果在132,則在分區1,其他類推。

該算法與取模範圍算法類似,截取長度爲prefixLength的子串,再對子串中每個字符的ASCII碼進行求和得出sum,然後對sum進行求模運算(sum%patternValue),可以計算出prefixLength長度的子串分片數。

應用指定的算法

在運行階段由應用自主決定路由到哪個分片,配置如下:

<tableRule name="sharding-by-substring">
    <rule>
        <columns>user_id</coluns>
        <algorithm>sharding-by-substring</algorithm>
    </rule>
</tableRule>
<function name="sharding-by-substring" class="org.opencloudb.route.function.PartitionBySubString">
    <property name="startIndex">0</property>
    <property name="size">2</property>
    <property name="partitionCount">8</property>
    <property name="defaultPartition">0</property>
</function>
  • columns標識將要分片的表字段。
  • algorithm爲分片函數

直接根據字符子串(必須是數字)計算分區號(由應用傳遞參數,顯式指定分區號)。例如user_id=05-100000002,其中user_id是從startIndex=0開始的,截取長度爲兩位數字,即05,05就是獲取的分區,默認分配到defaultPartition。

字符串hash解析算法

截取字符串中的int數組hash分片,配置如下:

<tableRule name="sharding-by-stringhash">
    <rule>
        <columns>user_id</coluns>
        <algorithm>sharding-by-stringhash</algorithm>
    </rule>
</tableRule>
<function name="sharding-by-stringhash" class="org.opencloudb.route.function.PartitionByString">
    <property name="length">512</property>
    <!-- zero base -->
    <property name="count">2</property>
    <property name="hashSlice">0:2</property>
</function>
  • columns標識將要分片的表字段。
  • algorithm爲分片函數
  • length爲字符串hash的求模基數
  • count爲分區數
  • hashSlice爲預算位,即根據子字符串中的int值進行hash運算。

規則如下:

"2" -> (0,2)
"1:2" -> (1,2)
"1:" -> (1,0)
"-1:" -> (-1,0)
":-1" -> (0,-1)
":" -> (0,0)

一致性hash算法

一致性hash算法有效解決了分佈式數據的擴容問題,配置如下:

<tableRule name="sharding-by-murmur">
    <rule>
        <columns>user_id</coluns>
        <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>

按日期(天)分片算法

<tableRule name="sharding-by-date">
    <rule>
        <columns>create_time</coluns>
        <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>
  • columns標識將要分片的表字段。
  • algorithm爲分片函數
  • dateFormat爲日期格式
  • sBeginDate爲開始日期
  • sEndDate爲結束日誌
  • sPartionDay爲分區天數,默認從開始日期算起,每個10天一個分區
    如果配置了sEndDate,則代表數據達到了這個日期的分片後會重複從開始分片插入。

按單月小時算法

單月內按照小時拆分,最小粒度爲小時,一天最火可以有24個分片,最少1個分片,下個月從頭開始循環,每個月末需要手動清理數據。

<tableRule name="sharding-by-hour">
    <rule>
        <columns>create_time</coluns>
        <algorithm>sharding-by-hour</algorithm>
    </rule>
</tableRule>
<function name="sharding-by-hour" class="org.opencloudb.route.function.LatestMonthPartion">
    <property name="splitOneDay">24</property>
</function>
  • columns標識將要分片的表字段。
  • algorithm爲分片函數
  • splitOneDay爲一天切分的分片數

自然月分片算法

使用場景爲按月份分區,每一個自然月一個分區,查詢條例時使用between and,配置如下:

<tableRule name="sharding-by-month">
    <rule>
        <columns>create_time</coluns>
        <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>
  • columns標識將要分片的表字段。
  • algorithm爲分片函數
  • dateFormat爲日期格式
  • sBeginDate爲開始日期

日期範圍hash算法

其思想與範圍求模一致,由於日期取模方法會出現數據熱點問題,所以先根據日期分組,再根據時間hash使得短期內數據分佈得更均勻。其優點是可以避免擴容時的數據遷移,又可以在一定程度上避免範圍分片的熱點問題,要求日期格式儘量精確,不然達不到局部均勻的目的。

<tableRule name="rangeDateHash">
    <rule>
        <columns>create_time</coluns>
        <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>
  • columns標識將要分片的表字段。
  • algorithm爲分片函數
  • sBeginDate爲開始日期,和dateFormat格式一致
  • sPartionDay代表多少天一組
  • dateFormat爲指定的日期格式,符合Java標準
  • groupPartionSize爲每組的分片數量
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章