consistent hash(一致性雜湊演算法)

來源:互聯網
上載者:User

一、產生背景

今天咱不去長篇大論特別詳細地講解consistent hash,我爭取用最輕鬆的方式告訴你consistent hash演算法是什麼,如果需要深入,Google一下~。

舉個栗子吧:

比如有 N 個 cache 伺服器,需要將一個object 映射到 N 個 cache 上,我們可以用類似下面的方法計算 object 的 hash 值,然後均勻的映射到到 N 個 cache 上:

hash(object)%N

比如object是“hello”,hash(object)是100,N為3,100%3=1,這個資料會被存到第1個cache上(0、1、2三個cache)。這樣就能解決一堆資料放到N個cache上的問題。

現在有個突發情況,0、1、2三個cache中1損壞了!

怎麼辦呢,cache 1上的資料首先需要遷移,可用cache數量變為2,這個時候我們需要重新計算所有資料的hash值,上面的公式變成了這樣:

hash(object)%(N-1)

這次重新計算意味著每一份資料hash之後的結果幾乎都變了!也就是意味著在cache系統中會發生大規模cache失效,資料訪問會直接衝擊cache後面的伺服器,好玩了,崩了。

咋個辦呢,consistent hash出現了!

二、演算法原理

  consistent hash簡單的說,就是要在cache數量變化時,能夠儘可能小的改變已存在 key 映射關係,也就是增加一個cache或者減少一個cache伺服器,對已經存在的快取資料不要產生大影響。怎麼做到呢,,,

  我們先想象一條鏈子,第一個格子是0,最後一個格子是2^32-1,這條鏈子就是一個地址空間為2^32的hash值空間,現在將鏈子首位相連,組成一個ring,就像下面這樣(這裡畫圖太麻煩了,下面的環環相關的圖來自互連網,侵刪吧):

  然後考慮我們由object1~object4這樣四個資料,通過hash演算法後映射到這個ring上【類似這樣:hash(object1)=key1】

  這裡應該很好理解,4個資料得到4個key,接下來我們要將cache伺服器也映射到這個ring上,假設由3個cache伺服器,分別是cache A、cache B、cache C,然後用hash演算法:hash(cache A)=key A,將3個cache伺服器丟到這個ring上,就可用得到如下結果(計算cache伺服器的hash值時可以用其ip等資訊):

  然後順著這個ring,收集object資料,遇到cache的時候就丟進去,這樣就可以將資料和cache對應起來,於是我們可以得到如下結果:

object1:Cache A

object4:Cache B

object2/object3: Cache C

  ok,這樣就完成了資料對應,然後我們考慮一下前面普通hash演算法遇到的cache伺服器數量變化的情況,看一下ring hash是否解決了這個問題。

  假設cache B掉線

  這個時候可以發現只有原先映射到Cache B上的object4收到了影響,需要轉移到Cache C上。

  如果增加一個Cache結點呢?假設增加一個Cache D:

  這個時候只需要將object2轉移到Cache D上,其他的沒有變化。是不是很神奇?

  這裡可能大家會意識到一個問題,當cache伺服器數量少的時候,這個演算法很容易導致資料分布不均勻,所以ring hash中還有一個虛擬節點的概念,前面只剩下cache A和cache C的例子中A上有1個資料,而C中存了3個,我們將cache(假設用ip值表示)加上一個編號,然後進行hash運算,得到更多的虛擬cache結點:

hash("192.168.0.1#1")

hash("192.168.0.1#2")

hash("192.168.0.2#1")

hash("192.168.0.2#2")

  類似上面這樣,一個cache伺服器就對應了2個hash值,這樣我們再丟到ring上就會得到如下結果:

  這時候object1就會落在Cache A2上,object2會落在Cache A1上,物理上其實A1和A2都是cache A,通過這種方式直觀看我們將原先的1、3分布變成了2、2分布(A上1個資料C上3個資料變成A上2個資料B上2個資料)

  引入“虛擬節點”後,映射關係就從 { 對象 -> 節點 } 轉換到了 { 對象 -> 虛擬節點 },於是乎這個演算法的平衡性就更好了。

  ok,一致性hash演算法的原理就介紹到這裡,下面可以看groupcahce中的consistent hash如何?了。

三、groupcache中的consistent hash

  終於要看代碼了!!!

  源碼主要就如下幾個package,今天我們看一下第一個package:【package consistenthash】的內容

 

  從我們可以看到,這裡只需要關注consistenthash.go這源碼檔案,裡面有2個類型:Hash和Map,1個函數New,Map類型有4個不可匯出的屬性以繼3個綁定的方法。

下面一個個看吧~

  1、類型Hash(需要記得Hash是一個函數類型哦)。

 

  2、Map類型(Map類型的第一個屬性就是上面的Hash類型變數hash,replicas屬性工作表示的是副本數,還記得上面我們提到的為瞭解決平衡性問題而引入的虛擬節點的概念嗎?這些虛擬節點這是這裡描述的副本數)。

 

  3、New()函數(這個函數明顯就是用來擷取上面的Map類型變數執行個體的,初始化副本數、hash函數、hashMap表,hashMap表的key是一個表示cache伺服器或者副本的hash值,value為一個具體的cache伺服器,這樣就完成了Cache A、Cache A1、Cache A2等副本全部映射到Cache A的功能。

 

  4、IsEmpty()函數(這個函數就沒啥可講的了,非空判斷)

 

  5、Add()函數(將快取服務器加到Map中,比如Cache A、Cache B作為keys,如果副本數指定的是2,那麼Map中存的資料是Cache A#1、Cache A#2、Cache B#1、Cache B#2的hash結果)

 

  6、Get()函數(這個函數相對複雜一點,比如有一個資料:name="張三"這條資料需要存,這時候通過這個函數選擇一個cache伺服器,返回的string類型可以是伺服器ip,比如:"192.168.0.1",從而調用者能夠將name="張三"存到"192.168.0.1"上)

 

  ok,講完了,今天的內容有點多,可能需要多花點時間消化一下~

  下一講我們介紹groupcachepb這個package,當然不可避免地要介紹一下Protocol Buffers了,行,今天就講到這裡!

149 次點擊  
相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.