天天看點

資料庫中間件分片算法之hash

前言

夜深人靜的時候,打開

雲音樂

,點上一曲

攀登

,帶上真無線藍牙耳機,瞬間燃到爆,鍵盤打字如飛倦意全無。

分片規則

這幾天有人問我,dble和MyCat到底有什麼不同。其實dble作為MyCAT的同門,吸收了MyCat的精華,同時也相應的做了一些減法。隻支援MySQL顯得更加的純粹。是以選擇對比學習兩者我覺得挺好。

前面我們學習了schema.xml檔案的配置,我們能獨立的把

邏輯庫

邏輯表

搭建起來,讓資料表跟随我們的定義規則(取模)進行分布。今天我們介紹具體的分片算法。

dble

相對于

mycat

來說,是做了一些減法的。比如一緻hash算法就沒有,而是使用了

jumpstringhash

代替了一緻性hash。具體原因可以參考文章

dble 沿用 jumpstringhash,移除 Mycat 一緻性 hash 原因

  1. hash分區算法

  2. stringhash分區算法
  3. enum分區算法
  4. numberrange分區算法
  5. patternrange分區算法
  6. date分區算法
  7. jumpstringhash算法

HASH分區算法

Hash分區算法是一種比較典型而且常用的算法。要使用HASH分區算法需要在rule.xml中定義兩個部分。

分區規則定義

如下所示,使用

tableRule

标簽定義,name對應的是規則的名字,而

rule

标簽中的

columns

則對應的分片字段,這個字段必須和表中的字段一緻。

algorithm

則代表了執行分片函數的名字。

<tableRule name="auto-sharding-long">
<rule>
<columns>id</columns>
<algorithm>rang-long</algorithm>
</rule>
</tableRule>           

分區算法定義

function

标簽定義分區算法,name代表算法的名字,算法的名字要和上面的tableRule中的标簽相對應。

class

:指定分區算法實作類。

property

指定了對應分區算法的參數。不同的算法參數不同。

<function name="rang-long" class="com.actiontech.dble.route.function.AutoPartitionByLong">
<property name="mapFile">auto-sharding-long.txt</property>
...
</function>           
  • partitionCount

    :指定分區的區間數,具體為 C1 +C2 + ... + Cn
  • partitionLength

    :指定各區間長度,具體區間劃分為 [0, L1), [L1, 2L1), ..., [(C1-1)L1, C1L1), [C1L1, C1L1+L2), [C1L1+L2, C1L1+2L2), ... 其中,每一個區間對應一個資料節點。

測試Hash分區算法

1.在啟動的時候,兩個數組點乘做運算,得到取模數。

資料庫中間件分片算法之hash

2.兩個數組進行叉乘,得出實體分區表。

資料庫中間件分片算法之hash

3.根據where條件的值來落入實際分片

select * from shareding_key = 999;           

先根據分片鍵取出999,按照公式1的計算結果除取模,然後得到的值落到2計算出來的分片中。

4.舉個簡單的例子:

<property name="partitionCount">2,3</property>
<property name="partitionLength">100,50</property>           

根據公式1

資料庫中間件分片算法之hash

也就是傳進來的值需要對350取模。

根據公式2,實體分區為

資料庫中間件分片算法之hash

999對350取模,正好是299。落在250-300這個區間裡面。也就是第4個區間。

接下來我們實際來測試一下,我們在rule.xml中設定如下:

<tableRule name="rule_hash">
    <rule>
        <columns>id</columns>
        <algorithm>func_hash_test</algorithm>
    </rule>
</tableRule>

<function name="func_hash_test" class="Hash">
    <property name="partitionCount">2,3</property>
    <property name="partitionLength">100,50</property>
</function>           

我們通過公式2算出有5個分片。是以在schema.xml中設定table屬性如下:

<table name="hash_test" primaryKey="id" rule="rule_hash" dataNode="dn1,dn2,dn3,dn4,dn5"/>           

5.建立表測試

我們先使用shell建立1000行資料,在建立表,通過load data文法将我們shell産生的檔案進行導入。

for i in  {1..1000}
do
echo  $i'|name'$[i]'' >>a1.txt 
done           
資料庫中間件分片算法之hash

請原諒我作為一個GEEK,把桌面和終端完美結合成二次元是标配。

這裡可以看到我們查詢999這個資料,會自動到dn4這個分片上進行查詢。再比如我們查500,500對350取模是150,150是落在第二個分區裡面的。

6.另一個例子

<property name="partitionCount">2</property>
<property name="partitionLength">1000</property>           

此時C _L=2_1000=2000,将對2000進行取模。

同時将劃分如下的分區:

資料庫中間件分片算法之hash

注意事項

  1. M不能大于2880。2880的原因是這樣的:2, 3, 4, 5, 6, 8, 9, 10, 12, 15, 16, 18, 20, 24, 30, 32, 36, 40, 45, 48, 60, 64, 72, 80, 90, 96, 120, 144, 160, 180, 192, 240, 288, 320, 360, 480, 576, 720, 960, 1440是2880的約數,這樣預分片擴容友善。
  2. N必須要等于schema.xml中使用該分區算法的邏輯表的dataNode屬性指定的DataNode數量之和,比如我們上面這個算法是5個分區,但是如果你在邏輯表的dataNode屬性中設定分區個數小于5,dataNode="dn1,dn2,dn3,dn4",則dble就會報錯。

    partition size : 5 > table datanode size : 4 please make sure table datanode size = function partition size

  3. $C\_n$和$L\_n$的個數必須相等。
  4. 分區字段必須為整型字段,如果是其他類型,要求值可轉化為數字。
  5. 當partitionLength為1時,hash分區算法退化為求模算法,M及N均為partitionCount的值。
  6. NULL作為分片列的值的時候資料的結果恒落在0号節點(第一個節點上),建議最好不要讓這種情況出現,強制設定分片鍵為not null。

後記

今天學習了分片算法Hash。後續将繼續分享其他的算法。謝謝支援!