1. 程式人生 > >mycat分散式mysql中介軟體(分片規則)

mycat分散式mysql中介軟體(分片規則)

mycat 分片規則

     傳統的分片策略都是基於單表,或者分片基於主鍵進行分配,或者某些場景下需要多個表依賴於一個分片,或者分片的欄位並不是主鍵。

     a.  對於傳統的資料庫分片方式都是基於單個表格,對於表關聯這種操作,則很難處理。為了能夠執行t_usert_user_detail的聯合查詢, MyCAT借鑑了NewSQL領域的新秀Foundation DB的設計思路,Foundation DB創新性的提出了Table Group的概念,其將子表的儲存位置依賴於主表,並且物理上緊鄰存放,因此徹底解決了JOIN的效率和效能問題,根據這一思路,提出了基於E-R關係的資料分片策略,子表的記錄與所關聯的父表記錄存放在同一個資料分片上。

以t_user與t_user_detail例子為例,schema.xml中定義如下的分片配置:

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

t_user採用mod-long這個分片策略,分片在dn1-dn32上,t_user_detail依賴父表進行分片,兩個表的關聯關係為t_user_detail.user_id=t_user.id。於是資料分片和儲存的示意圖如下:

這樣一來,分片dn1-32上的t_user與hn1-32上的t_user_detail就可以進行區域性的JOIN聯合,再合併兩個節點的資料即可完成整體的JOIN,試想一下,每個分片上t_user_detail表有1000萬條,則10個分片就有1個億,基於E-R對映的資料分片模式,基本上解決了80%以上的企業應用所面臨的問題。

 b. 

多對多的表格如何處理?多對多的表格通常情況下,有以下幾種:

l  主表+關係表+字典表

l  主表A+關係表+主表B

對於第一種,字典表可以被定義為“全域性表”,字典表的記錄規模可以在幾千到幾十萬之間,基本是變動比較少的表,由MyCAT自動實時同步到所有分片,這樣就可以三個表都做JOIN操作了。

對於第二種,需要從業務角度來看,關係表更偏向哪個表,即“A的關係”還是“B的關係”,來決定關係表跟從那個方向儲存。目前還暫時無法很好支援這種模式下的3個表之間的關聯。未來版本中將考慮將中間表進行雙向複製,以實現從A-關係表 以及B-關係表的雙向關聯查詢。

關於全域性表的實現方式,全域性表在資料插入或更新的時候,會自動在全域性表定義的所有資料節點上執行相同的操作,以保證所有資料節點都一致,由於這個特性,全域性表可以跟任何分片或不分片的表格進行JOIN操作。對資料更新不頻繁的,規模不是很大的(100萬之內)的表都可以定義為MyCAT的全域性表,以實現用儲存換效能的目標。

配置為:

<table name="t_area" primaryKey="id" type="global" dataNode="dn1,dn2"/>

c.  主鍵分片vs 非主鍵分片

當你沒人任何欄位可以作為分片欄位的時候,主鍵分片就是唯一選擇,其優點是按照主鍵的查詢最快,當採用自動增長的序列號作為主鍵時,還能比較均勻的將資料分片在不同的節點上。

若有某個合適的業務欄位比較合適作為分片欄位,則建議採用此業務欄位分片,選擇分片欄位的條件如下:

  • 儘可能的比較均勻分佈資料到各個節點上;
  • 該業務欄位是最頻繁的或者最重要的查詢條件。

常見的除了主鍵之外的其他可能分片欄位有“訂單建立時間”、“店鋪類別”或“所在省”等。當你找到某個合適的業務欄位作為分片欄位以後,不必糾結於“犧牲了按主鍵查詢記錄的效能”,因為在這種情況下,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>

對於非主鍵分片的table,填寫屬性primaryKey,此時MyCAT會將你根據主鍵查詢的SQL語句的第一次執行結果進行分析,確定該Table 的某個主鍵在什麼分片上,並進行主鍵到分片ID的快取。

     第二次或後續查詢mycat會優先從快取中查詢是否有id-->node  即主鍵到分片的對映,如果有直接查詢,通過此種方法提高了非主鍵分片的查詢效能。
d.分片join

     不管是按照何種規則分片資料的join都是分散式系統難題,mycat提供了幾種方式:

     1. 如果是全域性表,分片內部的表相關與全域性表join,分片內部會使用分片內部全域性表join業務表,方式跨分片join

     2. E-R 關係的分片表,同樣也只會發生分片內部join 即 父表join子表,也不會跨分片

     3. catlet  既不是全域性不又不是E-R關係,mycat提供了人工智慧分片join即,通過程式程式設計的方式,通過攔截sql語句,將多個表的join分拆成多個子select,

        然後再join,這種方式需要開發支援,編寫java程式碼作為外掛,此種方法的優點是無需修改應用程式碼,只需要攔截對應的sql做處理即可。

     4. 目前最新版mycat引入了分片join機制,即通過在查詢時刻拉取join表的資料,同步到mycat本地,匯入到NoSql資料庫中,再做join order limit,

        目前此種方式為開發的最新方式,可以支援2個表誇分片join,無需特殊配置。

e. 主鍵生成方式

    主鍵的生成可以自己生成也可以由mycat提供方式解決,目前mycat提供了全域性唯一主鍵的策略。分為檔案方式,資料庫方式兩種。

全域性序列號是MyCAT提供的一個新功能,為了實現分庫分表情況下,表的主鍵是全域性唯一,而預設的MySQL的自增長主鍵無法滿足這個要求。全域性序列號的語法符合               標準SQL規範,其格式為:

next value for MYCATSEQ_GLOBAL

其中MYCATSEQ_GLOBAL是序列號的名字,MyCAT自動建立新的序列號,免去了開發的複雜度,另外,MyCAT也提供了一個全域性的序列號,名稱                             為:MYCATSEQ_GLOBAL。

注意,MYCATSEQ_必須大寫才能正確識別。

MyCAT溫馨提示:實踐中,建議每個表用自己的序列號,序列號的命名建議為MYCATSEQ _tableName_ID_SEQ。

從MyCAT 1.3開始,支援自增長主鍵,依賴於全域性序列號機制,建議採用資料庫方式的全域性序列號,並正確設定步長,以免影響實際效能。

         首先要開啟資料庫方式的全域性序列號,對於需要定義自增長主鍵的表,建立對應的全域性序列號,與table名稱同名大寫,如customer序列名為CUSTOMER,然後再 schema.xml 中對customer表的table元素增加屬性autoIncrement值為true.

 <table name=”CUSTOMER”  autoIncrement=”true”>

執行insert into customer (name,company_id,sharding_id) values ('test',2,10000);檢視效果, 暫不支援主鍵為null如:insert into customer (id,name,company_id,sharding_id) values (null,'test',2,10000);

Catlet 人工智慧分片使用:

Mycat 1.3開始支援Java類程式設計方式實現複雜SQL處理,類似資料庫的儲存過程,Catlet是一個實現了Catlet介面的無狀態Java類,負責將編碼實現某個SQL的處理過程,並返回響應報文給客戶端,目前主要用於人工智慧(非AI)編碼實現跨分片SQL的處理邏輯,Demo中附帶143行完成兩個表JION的查詢示例,採用流式處理機制,未來將會提供更多高質量API來簡化跨分片複雜SQL的程式設計問題,下個版本有望實現不帶子查詢的兩表關聯查詢自動處理,也採用此框架。

package org.opencloudb.sqlengine; /** * mycat catlet ,used to execute sql and return result to client,some like * database's procedure. * must implemented as a stateless class and can process many SQL concurrently * * @author wuzhih * */public interface Catlet {     /*     * execute sql in EngineCtx and return result to client     */    void processSQL(String sql, EngineCtx ctx); Catlet 編寫完成並編譯通過以後,必須放在Mycat_home/catlets目錄下,系統會動態載入相關class(需要按照Java Class的目錄結構存放,比如com\hp\catlet\XXXCatlet.class,目前還不支援Jar檔案)並每隔1分組掃描一次檔案是否更新,若更新則自動重新載入,因此無需重啟服務,下面的截圖對應的是demo.catletes.MyHellowJion這個Catlet的目錄結構和所有相關類的位置。在Mysql命令列連線Mycat Server後,執行帶Catlet註解的SQL,則啟動具體的Catlet完成SQL的解析,如下面的例子,表明select a.*, b.title from travelrecord a ,hotnews b where a.id=b.id 這個SQL交給demo.catlets.MyHellowJoin來處理。/*!mycat:catlet=demo.catlets.MyHellowJoin */select a.*, b.title from travelrecord a ,hotnews b where a.id=b.id         想要執行上述Demo,可以將demo.catletes.MyHellowJion編譯好,並將Class放入指定的目錄,執行上述SQL。此外Demo原始碼存在於demo.catlets目錄下,這部分是屬於Mycat開發,具備Java開發能力並有這方面需求的同學,可以參考另一片文章《MyCAT人工智慧解決跨分片SQL》瞭解詳情。

常用的根據主鍵或非主鍵的分片規則配置:

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=010010=1DEFAULT_NODE=1

上面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:ffffffff    
*/

2.固定分片hash演算法

<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>

配置說明:

上面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 |
        // | 共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>

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>  </function>
# range start-end ,data node index# K=1000,M=10000.0-500M=0500M-1000M=11000M-1500M=2或0-10000000=010000001-20000000=1

配置說明:

上面columns 標識將要分片的表字段,algorithm 分片函式,

rang-long 函式中mapFile代表配置檔案路徑

所有的節點配置都是從0開始,及0代表節點1,此配置非常簡單,即預先制定可能的id範圍到某個分片

4.求模法

<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> 

配置說明:

上面columns 標識將要分片的表字段,algorithm 分片函式,

此種配置非常明確即根據id進行十進位制求模預算,相比方式1,此種在批量插入時需要切換資料來源,id不連續


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="sPartionDay">10</property>  </function>

配置說明:

上面columns 標識將要分片的表字段,algorithm 分片函式,

配置中配置了開始日期,分割槽天數,即預設從開始日期算起,分隔10天一個分割槽
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"));


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>
partition-pattern.txt 
# id partition range start-end ,data node index###### first host configuration1-32=033-64=165-96=297-128=3######## second host configuration129-160=4161-192=5193-224=6225-256=70-0=7

配置說明:

上面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));

7. ASCII碼求模通配

<tableRule name="sharding-by-prefixpattern">      <rule>        <columns>user_id</columns>        <algorithm>sharding-by-prefixpattern</algorithm>      </rule>   </tableRule><function name="sharding-by-prifixpattern" 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# range start-end ,data node index# ASCII# 48-57=0-9# 64銆�[email protected]銆丄-Z# 97-122=a-z###### first host configuration1-4=05-8=19-12=213-16=3###### second host configuration17-20=421-24=525-28=629-32=70-0=7

配置說明:

上面columns 標識將要分片的表字段,algorithm 分片函式,patternValue 即求模基數,prefixLength ASCII 擷取的位數

mapFile 配置檔案路徑

配置檔案中,1-32 即代表id%256後分布的範圍,如果在1-32則在分割槽1,其他類推 

此種方式類似方式6只不過採取的是將列種獲取前prefixLength位列所有ASCII碼的和進行求模sum%patternValue ,獲取的值,在通配範圍內的

即 分片數,

/**
* ASCII編碼:
* 48-57=0-9阿拉伯數字
* 64、[email protected]、A-Z
* 97-122=a-z
*
*/

如 

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));

8.程式設計指定

<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>

配置說明:

上面columns 標識將要分片的表字段,algorithm 分片函式 

此方法為直接根據字元子串(必須是數字)計算分割槽號(由應用傳遞引數,顯式指定分割槽號)。

例如id=05-100000002

在此配置中代表根據id中從startIndex=0,開始,擷取siz=2位數字即05,05就是獲取的分割槽,如果沒傳預設分配到defaultPartition

9.字串hash解析

<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>

配置說明:

上面columns 標識將要分片的表字段,algorithm 分片函式 

函式中length代表字串hash求模基數,count分割槽數,hashSlice hash預算位

即根據子字串 hash運算

hashSlice : 0 means str.length(), -1 means str.length()-1

/**
     * "2" -&gt; (0,2)<br/>
     * "1:2" -&gt; (1,2)<br/>
     * "1:" -&gt; (1,0)<br/>
     * "-1:" -&gt; (-1,0)<br/>
     * ":-1" -&gt; (0,-1)<br/>
     * ":" -&gt; (0,0)<br/>
     */
例子:

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));

10,一致性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>
一致性hash預算有效解決了分散式資料的擴容問題,前1-9中id規則都多少存在資料擴容難題,而10規則解決了資料擴容難點

關於一致性hash詳細:

一致性雜湊演算法在1997年由麻省理工學院提出的一種分散式雜湊(DHT)實現演算法,設計目標是為了解決因特網中的熱點(Hot spot)問題,初衷和CARP十分類似。一致性雜湊修正了CARP使用的簡 單雜湊演算法帶來的問題,使得分散式雜湊(DHT)可以在P2P環境中真正得到應用。      一致性hash演算法提出了在動態變化的Cache環境中,判定雜湊演算法好壞的四個定義:
1、平衡性(Balance):平衡性是指雜湊的結果能夠儘可能分佈到所有的緩衝中去,這樣可以使得所有的緩衝空間都得到利用。很多雜湊演算法都能夠滿足這一條件。
2、單調性(Monotonicity):單調性是指如果已經有一些內容通過雜湊分派到了相應的緩衝中,又有新的緩衝加入到系統中。雜湊的結果應能夠保證原有已分配的內容可以被對映到原有的或者新的緩衝中去,而不會被對映到舊的緩衝集合中的其他緩衝區。 
3、分散性(Spread):在分散式環境中,終端有可能看不到所有的緩衝,而是隻能看到其中的一部分。當終端希望通過雜湊過程將內容對映到緩衝上時,由於不同終端所見的緩衝範圍有可能不同,從而導致雜湊的結果不一致,最終的結果是相同的內容被不同的終端對映到不同的緩衝區中。這種情況顯然是應該避免的,因為它導致相同內容被儲存到不同緩衝中去,降低了系統儲存的效率。分散性的定義就是上述情況發生的嚴重程度。好的雜湊演算法應能夠儘量避免不一致的情況發生,也就是儘量降低分散性。 
4、負載(Load):負載問題實際上是從另一個角度看待分散性問題。既然不同的終端可能將相同的內容對映到不同的緩衝區中,那麼對於一個特定的緩衝區而言,也可能被不同的使用者對映為不同 的內容。與分散性一樣,這種情況也是應當避免的,因此好的雜湊演算法應能夠儘量降低緩衝的負荷。
    在分散式叢集中,對機器的新增刪除,或者機器故障後自動脫離叢集這些操作是分散式叢集管理最基本的功能。如果採用常用的hash(object)%N演算法,那麼在有機器新增或者刪除後,很多原有的資料就無法找到了,這樣嚴重的違反了單調性原則。接下來主要講解一下一致性雜湊演算法是如何設計的: 環形Hash空間 按照常用的hash演算法來將對應的key雜湊到一個具有2^32次方個桶的空間中,即0~(2^32)-1的數字空間中。現在我們可以將這些數字頭尾相連,想象成一個閉合的環形。如下圖 把資料通過一定的hash演算法處理後對映到環上 現在我們將object1、object2、object3、object4四個物件通過特定的Hash函式計算出對應的key值,然後雜湊到Hash環上。如下圖:     Hash(object1) = key1;     Hash(object2) = key2;     Hash(object3) = key3;     Hash(object4) = key4;
將機器通過hash演算法對映到環上 在採用一致性雜湊演算法的分散式叢集中將新的機器加入,其原理是通過使用與物件儲存一樣的Hash演算法將機器也對映到環中(一般情況下對機器的hash計算是採用機器的IP或者機器唯一的別名作為輸入值),然後以順時針的方向計算,將所有物件儲存到離自己最近的機器中。 假設現在有NODE1,NODE2,NODE3三臺機器,通過Hash演算法得到對應的KEY值,對映到環中,其示意圖如下: Hash(NODE1) = KEY1; Hash(NODE2) = KEY2; Hash(NODE3) = KEY3;
通過上圖可以看出物件與機器處於同一雜湊空間中,這樣按順時針轉動object1儲存到了NODE1中,object3儲存到了NODE2中,object2、object4儲存到了NODE3中。在這樣的部署環境中,hash環是不會變更的,因此,通過算出物件的hash值就能快速的定位到對應的機器中,這樣就能找到物件真正的儲存位置了。 機器的刪除與新增 普通hash求餘演算法最為不妥的地方就是在有機器的新增或者刪除之後會照成大量的物件儲存位置失效,這樣就大大的不滿足單調性了。下面來分析一下一致性雜湊演算法是如何處理的。 1. 節點(機器)的刪除     以上面的分佈為例,如果NODE2出現故障被刪除了,那麼按照順時針遷移的方法,object3將會被遷移到NODE3中,這樣僅僅是object3的對映位置發生了變化,其它的物件沒有任何的改動。如下圖:
2. 節點(機器)的新增      如果往叢集中新增一個新的節點NODE4,通過對應的雜湊演算法得到KEY4,並對映到環中,如下圖:
    通過按順時針遷移的規則,那麼object2被遷移到了NODE4中,其它物件還保持這原有的儲存位置。通過對節點的新增和刪除的分析,一致性雜湊演算法在保持了單調性的同時,還是資料的遷移達到了最小,這樣的演算法對分散式叢集來說是非常合適的,避免了大量資料遷移,減小了伺服器的的壓力。 平衡性 根據上面的圖解分析,一致性雜湊演算法滿足了單調性和負載均衡的特性以及一般hash演算法的分散性,但這還並不能當做其被廣泛應用的原由,因為還缺少了平衡性。下面將分析一致性雜湊演算法是如何滿足平衡性的。hash演算法是不保證平衡的,如上面只部署了NODE1和NODE3的情況(NODE2被刪除的圖),object1儲存到了NODE1中,而object2、object3、object4都儲存到了NODE3中,這樣就照成了非常不平衡的狀態。在一致性雜湊演算法中,為了儘可能的滿足平衡性,其引入了虛擬節點。     ——“虛擬節點”( virtual node )是實際節點(機器)在 hash 空間的複製品( replica ),一實際個節點(機器)對應了若干個“虛擬節點”,這個對應個數也成為“複製個數”,“虛擬節點”在 hash 空間中以hash值排列。 以上面只部署了NODE1和NODE3的情況(NODE2被刪除的圖)為例,之前的物件在機器上的分佈很不均衡,現在我們以2個副本(複製個數)為例,這樣整個hash環中就存在了4個虛擬節點,最後物件對映的關係圖如下:
根據上圖可知物件的對映關係:object1->NODE1-1,object2->NODE1-2,object3->NODE3-2,object4->NODE3-1。通過虛擬節點的引入,物件的分佈就比較均衡了。那麼在實際操作中,正真的物件查詢是如何工作的呢?物件從hash到虛擬節點到實際節點的轉換如下圖:
“虛擬節點”的hash計算可以採用對應節點的IP地址加數字字尾的方式。例如假設NODE1的IP地址為192.168.1.100。引入“虛擬節點”前,計算 cache A 的 hash 值: Hash(“192.168.1.100”); 引入“虛擬節點”後,計算“虛擬節”點NODE1-1和NODE1-2的hash值: Hash(“192.168.1.100#1”); // NODE1-1 Hash(“192.168.1.100#2”); // NODE1-2

以上所有規則每種都有特定使用場景,可以選擇性使用。

相關推薦

mycat分散式mysql中介軟體分片規則

mycat 分片規則      傳統的分片策略都是基於單表,或者分片基於主鍵進行分配,或者某些場景下需要多個表依賴於一個分片,或者分片的欄位並不是主鍵。      a.  對於傳統的資料庫分片方式都是基於單個表格,對於表關聯這種操作,則很難處理。為了能夠執行t_user與t

分散式訊息中介軟體——Kafka核心元件詳解

一、Kafka釋出訂閱訊息系統基礎      Kafka 是分散式釋出-訂閱訊息系統。它最初由 LinkedIn 公司開發,使用 Scala語言編寫,之後成為 Apache 頂級專案框架。Kafka

分散式訊息中介軟體——Flume+Kafka+Storm+Redis生態架構實戰

一、Kafka專案應用架構分析 1、Kafka生態架構        資料收集的速度,跟處理的速度不一定一致,故使用Kafka中介軟體作為資料收集和資料處理的一個Access入口,接收flume收集的資料,並通過kafkaSpout提交給Storm進行處理。 2、kafka

分散式訊息中介軟體——ActiveMQ點對點訊息模式

一、下載執行 1、官網下載      Windows版:apache-activemq-5.13.3-bin.zipLinux版:apache-activemq-5.13.3-bin.tar.gz 2、Windows下根據作業系統位數,執行activemq.bat檔案,啟動

入門篇-連線華為雲分散式資料庫中介軟體DDM

在成功配置DDM例項後,即可連線訪問DDM例項以及例項下的邏輯庫。 華為雲分散式資料庫中介軟體(DDM)服務目前管理的關係型資料庫,是基於MySQL作為儲存引擎,因此DDM服務相容MySQL大部分語法以及客戶端。關於DDM的使用受限說明,請參見SQL相容性。 DDM例項提

在node中介軟體微服務架構中,用一個node去部署多個專案比較好,還是一個專案對應一個node比較好?

第一種: 一個專案對應一個node服務; 優點:前端跟node也是可以獨立開發,降低耦合,也可單獨部署; 缺點:一個專案對應一個node,專案多的話,維護不方便; 第二種:一個node下,部署多個專案,可以以這個node作為底盤,在點選進入專案時,讓其載入該專案

01.什麼是中介軟體詳解

目錄   背景 正文 1. 由來 2. 中介軟體的起源 2.1 中介軟體發展的歷史 2.2 中介軟體發展的驅動力 3. 中介軟體的概念 3.1 中介軟體的特徵(內涵) 平臺化 應用支撐 軟體複用 耦合關係 互操作性 3.

MyCat:開源分散式資料庫中介軟體

為什麼需要MyCat? 雖然雲端計算時代,傳統資料庫存在著先天性的弊端,但是NoSQL資料庫又無法將其替代。如果傳統資料易於擴充套件,可切分,就可以避免單機(單庫)的效能缺陷。 MyCat的目標就是:低成本地將現有的單機資料庫和應用平滑遷移到“雲”端,解決資料儲存和業務規模迅速

訊息中介軟體分散式系統事務一致性解決方案大對比,誰最好使?

原文轉載至:https://blog.csdn.net/lovesomnus/article/details/51785108   在分散式系統中,同時滿足“一致性”、“可用性”和“分割槽容錯性”三者是不可能的。分散式系統的事務一致性是一個技術難題,各種解決方案孰優孰劣? 在OLTP系統領域,

華為雲分散式資料庫中介軟體DDM和開源MyCAT對比

前言 華為雲分散式資料庫中介軟體(Distributed Database Middleware)是解決資料庫容量、效能瓶頸和分散式擴充套件問題的中介軟體服務,提供分庫分表、讀寫分離、彈性擴容等能力,應對海量資料的高併發訪問場景,有效提升資料庫讀寫效能。 圖1:DDM產品介紹   DDM

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

1 MyCat分片規則 資料切分中重要的幾條原則,其中有幾條資料冗餘,表分組(Table Group)。 1.1全域性表 如果你的業務中有些資料類似於資料字典,比如配置檔案的配置,常用業務的配置或資料量不是很大,很少變動的表,這些表往往不是特別大,而且大部分的業務場景都

訊息中介軟體分散式系統事務一致性解決方案大對比,誰最好使?

在分散式系統中,同時滿足“一致性”、“可用性”和“分割槽容錯性”三者是不可能的。分散式系統的事務一致性是一個技術難題,各種解決方案孰優孰劣? 在OLTP系統領域,我們在很多業務場景下都會面臨事務一致性方面的需求,例如最經典的Bob給Smith轉賬的案例。傳統的企業開發,

mycat中介軟體linux版本mycat1.6版本安裝

前言 前面的文章,介紹了關於mycat的相關概念,為了簡要描述,故而去掉了有關mycat的起源等內容。 本節內容則是講述,如何安裝mycat1.6版本。 安裝前環境要求 環境要求如下: 環境 版本 mysql

開源的分散式資料庫中介軟體系統Mycat和阿里巴巴Cobar的對比

1,愕然回首,它在燈火闌珊處關於mysql叢集中介軟體,以前寫在應用程式裡面,由開發人員實現,在配置檔案裡面寫多個數據源,寫庫一個數據源,讀庫一個數據源,笨拙不高效,由於程式設計師的差異化,效果並不是特別理想。後來,組織了開發人員寫了一個自動識別讀寫的功能模組介面,讓開發人員呼叫,這樣能滿足特定場景的業務需求

mycat中介軟體描述

前言 mycat是開源的分散式資料庫系統,但實際上,按我的理解,只是一個類似於jdbc的資料庫管理中介軟體。通過mycat可以進行增刪改查,但是由於本身還未完善,資料庫中小部分比較複雜的語句,到目前的1.6版本都還沒有實現。 對於mycat,有人對

分散式資料庫中介軟體、產品——sharding-jdbc、mycat、drds

        一般對於業務記錄類隨時間會不斷增加的資料,當資料量增加到一定量(一般認為整型值為主的表達到千萬級,字串為主的表達到五百萬)的時候,效能將遇到瓶頸,同時調整表結構也會變得非常困難。為了避免生產遇到這樣的問題,在做系統設計時需要預估可能產生的資料量:預估記錄主體個

MySQL 中介軟體 Mycat 安裝與使用

環境        Windows (mycat)        Linux 虛擬機器(主庫)        Linux 虛擬機器(從褲)下載Windows 使用1. 解壓Windows包2. 配置 

mysql中介軟體研究Atlas,cobar,TDDL

mysql-proxy是官方提供的mysql中介軟體產品可以實現負載平衡,讀寫分離

MySQL-ProxySQL中介軟體| ProxySQL基本概念

目錄     MySQL-ProxySQL中介軟體(一)| ProxySQL基本概念: https://www.cnblogs.com/SQLServer2012/p/10972593.html     MySQL-ProxySQL中介軟體(二)| Adm

分散式資料庫中介軟體 MyCat 搞起來!

關於 MyCat 的鋪墊文章已經寫了三篇了: MySQL 只能做小專案?鬆哥要說幾句公道話! 北冥有 Data,其名為鯤,鯤之大,一個 MySQL 放不下! What?Tomcat 竟然也算中介軟體? 今天終於可以迎接我們的大 Boss 出場了! MyCat 簡介 前面文章我們提到,如果資料量比較大的話