1. 程式人生 > >圖解一致性hash演算法和實現

圖解一致性hash演算法和實現

更多內容,歡迎關注微信公眾號:全菜工程師小輝。公眾號回覆關鍵詞,領取免費學習資料。

一致性hash演算法是什麼?

一致性hash演算法,是麻省理工學院1997年提出的一種演算法,目前主要應用於分散式快取當中。
一致性hash演算法可以有效地解決分散式儲存結構下動態增加和刪除節點所帶來的問題。
在Memcached、Key-Value Store、Bittorrent DHT、LVS中都採用了一致性hash演算法,可以說一致性hash演算法是分散式系統負載均衡的首選演算法。

傳統hash演算法的弊端

常用的演算法是對hash結果取餘數 (hash() mod N):對機器編號從0到N-1,按照自定義的hash演算法,對每個請求的hash值按N取模,得到餘數i,然後將請求分發到編號為i的機器。但這樣的演算法方法存在致命問題,如果某一臺機器宕機,那麼應該落在該機器的請求就無法得到正確的處理,這時需要將宕掉的伺服器使用演算法去除,此時候會有(N-1)/N的伺服器的快取資料需要重新進行計算;如果新增一臺機器,會有N /(N+1)的伺服器的快取資料需要進行重新計算。對於系統而言,這通常是不可接受的顛簸(因為這意味著大量快取的失效或者資料需要轉移)。

> 傳統求餘做負載均衡演算法,快取節點數由3個變成4個,快取不命中率為75%。計算方法:窮舉hash值為1-12的12個數字分別對3和4取模,然後比較發現只有前3個快取節點對應結果和之前相同,所以有75%的節點快取會失效,可能會引起快取雪崩。

一致性hash演算法

  1. 首先,我們將hash演算法的值域對映成一個具有2<sup>32</sup> 次方個桶的空間中,即0~(2<sup>32</sup>)-1的數字空間。現在我們可以將這些數字頭尾相連,組合成一個閉合的環形。

  2. 每一個快取key都可以通過Hash演算法轉化為一個32位的二進位制數,也就對應著環形空間的某一個快取區。我們把所有的快取key對映到環形空間的不同位置。

  3. 我們的每一個快取節點也遵循同樣的Hash演算法,比如利用IP或者主機名做Hash,對映到環形空間當中,如下圖

image

  1. 如何讓key和快取節點對應起來呢?很簡單,每一個key的順時針方向最近節點,就是key所歸屬的快取節點。所以圖中key1儲存於node1,key2,key3儲存於node2,key4儲存於node3。

image

  1. 當快取的節點有增加或刪除的時候,一致性雜湊的優勢就顯現出來了。讓我們來看看實現的細節:
  • 增加節點
    當快取叢集的節點有所增加的時候,整個環形空間的對映仍然會保持一致性雜湊的順時針規則,所以有一小部分key的歸屬會受到影響。

image

有哪些key會受到影響呢?圖中加入了新節點node4,處於node1和node2之間,按照順時針規則,從node1到node4之間的快取不再歸屬於node2,而是歸屬於新節點node4。因此受影響的key只有key2。

image

最終把key2的快取資料從node2遷移到node4,就形成了新的符合一致性雜湊規則的快取結構。

  • 刪除節點 當快取叢集的節點需要刪除的時候(比如節點掛掉),整個環形空間的對映同樣會保持一致性雜湊的順時針規則,同樣有一小部分key的歸屬會受到影響。

image

有哪些key會受到影響呢?圖中刪除了原節點node3,按照順時針規則,原本node3所擁有的快取資料就需要“託付”給node3的順時針後繼節點node1。因此受影響的key只有key4。

image

最終把key4的快取資料從node3遷移到node1,就形成了新的符合一致性雜湊規則的快取結構。

> 說明:這裡所說的遷移並不是直接的資料遷移,而是在查詢時去找順時針的後繼節點,因快取未命中而重新整理快取。

> 計算方法:假設節點hash雜湊均勻(由於hash是散列表,所以並不是很理想),採用一致性hash演算法,快取節點從3個增加到4個時,會有0-33%的快取失效,此外新增節點不會環節所有原有節點的壓力。

一致性hash演算法的結果相比傳統hash求餘演算法已經進步很多,但可不可以改進一下呢?或者如果出現分佈不均勻的情況怎麼辦?比如下圖這樣,按順時針規則,所有的key都歸屬於統一個節點。

image

一致性hash演算法+虛擬節點

為了優化這種節點太少而產生的不均衡情況。一致性雜湊演算法引入了虛擬節點的概念。
所謂虛擬節點,就是基於原來的物理節點映射出N個子節點,最後把所有的子節點對映到環形空間上。

image

> 虛擬節點越多,分佈越均勻。使用一致性hash演算法+虛擬節點這種情況下,快取節點從3個變成4個,快取失效率為25%,而且每個節點都平均的承擔了壓力。

一致性hash演算法+虛擬節點的實現

原理理解了,實現並不難,主要是一些細節:

  1. hash演算法的選擇。Java程式碼不要使用hashcode函式,這個函式結果不夠雜湊,而且會有負值需要處理。 這種計算Hash值的演算法有很多,比如CRC32_HASH、FNV1_32_HASH、KETAMA_HASH等,其中KETAMA_HASH是預設的MemCache推薦的一致性Hash演算法,用別的Hash演算法也可以,比如FNV1_32_HASH演算法的計算效率就會高一些。
  2. 資料結構的選擇。根據演算法原理,我們的演算法有幾個要求:
  • 要能根據hash值排序儲存
  • 排序儲存要被快速查詢 (List不行)
  • 排序查詢還要能方便變更 (Array不行)

另外,由於二叉樹可能極度不平衡。所以採用紅黑樹是最穩妥的實現方法。Java中直接使用TreeMap即可。

更多內容,歡迎關注微信公眾號:全菜工程師小輝。公眾號回覆關鍵詞,領取免費學習資料。

哎呀,如果我的名片丟了。微信搜尋“全菜工程師小輝”,依   
 
 </div> 
 <div class=

相關推薦

圖解一致性hash演算法實現

更多內容,歡迎關注微信公眾號:全菜工程師小輝。公眾號回覆關鍵詞,領取免費學習資料。 一致性hash演算法是什麼? 一致性hash演

一致性Hash 分析實現

一致性Hash 分析和實現 ---title: 1.一致性Hashdate: 2018-02-05 12:03:22categories:- 一致性Hash--- 一下分析來源於網路總結:演算法參照自己實現,共參考和指正。 一致性Hash演算法背景   一致性雜湊演算法在1997年由麻省理工學院的Ka

一致性hash演算法程式碼實現

什麼是一致性hash 一致性雜湊演算法(Consistent Hashing Algorithm)是一種分散式演算法,常用於負載均衡。Memcached client也選擇這種演算法,解決將key-value均勻分配到眾多Memcached server上的問題。它可以取代傳統的取模操作

一致性hash介紹實現

http://www.cnblogs.com/zhangshiwen/p/5787232.html , 看了幾篇一致性hash的介紹, 這邊理論講的比較少,但是結合實際例子,容易理解。 mark.像Memcache以及其它一些記憶體K/V資料庫一樣,Redis本身不提供分散式

一致性hash演算法redis叢集動態資料儲存

記錄:對一致性Hash演算法,Java程式碼實現的深入研究連結地址: http://www.cnblogs.com/xrq730/p/5186728.html全部來自:https://mp.weixin.qq.com/s/yimfkNYF_tIJJqUIzV7TFAhttps

一致性Hash演算法實現

一致性hash作為一個負載均衡演算法,可以用在分散式快取、資料庫的分庫分表等場景中,還可以應用在負載均衡器中作為作為負載均衡演算法。在有多臺伺服器時,對於某個請求資源通過hash演算法,對映到某一個臺伺服器,當增加或減少一臺伺服器時,可能會改變這些資源對應的ha

一致性hash演算法 java實現

public class NoName { private static final Map<String,String> ipMap = new HashMap<String, String>(); private static f

memcache客戶端實現叢集之一致性hash演算法

一致性雜湊的演算法把取餘演算法的等於號來選擇mem伺服器變成了大於號來選擇mem伺服器,這應該是才是關鍵,可以使一個鍵的mem伺服器落點變成是動態選擇(一個伺服器down掉然後選擇crc32(key)後大於這個伺服器的落點....) 新增虛擬節點,虛擬節點其實還是原來那幾臺伺服器,每個虛擬節

一致性Hash演算法,Java程式碼實現

一致性Hash演算法 關於一致性Hash演算法,在我之前的博文中已經有多次提到了,MemCache超詳細解讀一文中"一致性Hash演算法"部分,對於為什麼要使用一致性Hash演算法、一致性Hash演算法的演算法原理做了詳細的解讀。 演算法的具體原理這裡再次貼上: 先構造

twemproxy0.4原理分析-一致性hash演算法實現ketama分析

概述 本文是一致性hash演算法的一種開原始碼的實現:ketama的原始碼分析。 本文是我多年前的一篇文章整理而來,以前的那篇文章的連結可以在這裡檢視。 簡介 若我們在後臺使用NoSQL叢集,必然會涉及到key的分配問題,叢集中某臺機器宕機時如何key又該如何分配的問題。

資料結構算法系列 - 一致性hash演算法

1 基本場景 比如你有 N 個 cache 伺服器(後面簡稱 cache ),那麼如何將一個物件 object 對映到 N 個 cache 上呢,你很可能會採用類似下面的通用方法計算 object 的 hash 值,然後均勻的對映到到 N 個 cache ; hash(object)%N

一致性Hash演算法,Java程式碼實現的深入研究

1 /** 2 * 帶虛擬節點的一致性Hash演算法 3 * @author 五月的倉頡 http://www.cnblogs.com/xrq730/ 4 */ 5 public class ConsistentHashingWithVirtualNode 6 { 7

memcache分散式 [一致性hash演算法] 的php實現

 最近在看一些分散式方面的文章,所以就用php實現一致性hash來練練手,以前一般用的是最原始的hash取模做 分散式,當生產過程中新增或刪除一臺memcache都會造成資料的全部失效,一致性hash就是為了解決這個問題,把失效資料降到最低,相關資料可以 google一下! php實現效率有一定的缺失,如

一致性hash演算法 java程式碼實現與測試

轉載:http://blog.csdn.net/pcceo1/article/details/51493934 寫了一個一致性hash的Java實現程式碼,演算法是用別人的,據說很好,然後自己做了一個測試,用執行緒池起了1000個執行緒,每個執行緒hash10000次,模

Nginx+Memcache+一致性hash算法 實現頁面分布式緩存(轉)

tps ons efi 策略 可擴展性 master () list roo 網站響應速度優化包括集群架構中很多方面的瓶頸因素,這裏所說的將頁面靜態化、實現分布式高速緩存就是其中的一個很好的解決方案... 1)先來看看Nginx負載均衡 Nginx負載均衡依賴自帶的 ng

關於什麼是一致性hash演算法

當需要分散式快取的時候,通過key的hash值分散資料儲存hash(n)%快取伺服器臺數,同時也可以快速查詢資料而不用遍歷所有的伺服器。如下圖: 但是這樣,當業務拓展想要增加一臺伺服器的話,要麼快取伺服器資料全部需要重新計算儲存 -----hash(n)%5 。 要麼需要遍歷所有快取伺服器。不夠靈活。

一致性Hash演算法的深入理解

總結: 1、使用一致性Hash演算法,儘管增強了系統的伸縮性,但是也有可能導致負載分佈不均勻,解決辦法就是使用虛擬節點代替真實節點,  2、Hash演算法的選擇上,首先我們考慮簡單的String.HashCode()方法,這個演算法的缺點是,相似的字串如N1(10.0.

分散式演算法(一致性Hash演算法)

一、分散式演算法     在做伺服器負載均衡時候可供選擇的負載均衡的演算法有很多,包括: 輪循演算法(Round Robin)、雜湊演算法(HASH)、最少連線演算法(Least Connection)、響應速度演算法(Response Time)、加權法

Java架構/一致性Hash演算法在資料庫分表中的實踐

最近有一個專案,其中某個功能單表資料在可預估的未來達到了億級,初步估算在90億左右。與同事詳細討論後,決定採用一致性Hash演算法來完成資料庫的自動擴容和資料遷移。整個程式細節由我同事完成,我只是將其理解併成文,供有相同問題的同行參考。 參看此文的兄弟,預設各位已經熟悉一致性hash

一致性Hash演算法在資料庫分表中的實踐

最近有一個專案,其中某個功能單表資料在可預估的未來達到了億級,初步估算在90億左右。與同事詳細討論後,決定採用一致性Hash演算法來完成資料庫的自動擴容和資料遷移。整個程式細節由我同事完成,我只是將其理解併成文,供有相同問題的同行參考。 參看此文的兄弟,預設各位已經熟悉一致性hash演算法了。此文僅僅闡述程式