要解決上述問題只需作到以下一點:保證對相同key的訪問會被髮送到相同的服務器。不少方法能夠實現這一點,最經常使用的方法是計算哈希。例如對於每次訪問,能夠按以下算法計算其哈希值:緩存
其中Hash是一個從字符串到正整數的哈希映射函數。這樣,若是咱們將Memcached Server分別編號爲0、一、2,那麼就能夠根據上式和key計算出服務器編號h,而後去訪問。dom
這個方法雖然解決了上面提到的兩個問題,可是存在一些其它的問題。若是將上述方法抽象,能夠認爲經過:分佈式
這個算式計算每一個key的請求應該被髮送到哪臺服務器,其中N爲服務器的臺數,而且服務器按照0 – (N-1)編號。函數
這個算法的問題在於容錯性和擴展性很差。所謂容錯性是指當系統中某一個或幾個服務器變得不可用時,整個系統是否能夠正確高效運行;而擴展性是指當加入新的服務器後,整個系統是否能夠正確高效運行。網站
一個設計良好的分佈式哈希方案應該具備良好的單調性,即服務節點的增減不會形成大量哈希重定位。一致性哈希算法就是這樣一種哈希方案。
下一步將各個服務器使用H進行一個哈希,具體能夠選擇服務器的ip或主機名做爲關鍵字進行哈希,這樣每臺機器就能肯定其在哈希環上的位置,這裏假設將上文中三臺服務器使用ip地址哈希後在環空間的位置以下:
接下來使用以下算法定位數據訪問到相應服務器:將數據key使用相同的函數H計算出哈希值h,通根據h肯定此數據在環上的位置,今後位置沿環順時針「行走」,第一臺遇到的服務器就是其應該定位到的服務器。
例如咱們有A、B、C、D四個數據對象,通過哈希計算後,在環空間上的位置以下:
根據一致性哈希算法,數據A會被定爲到Server 1上,D被定爲到Server 3上,而B、C分別被定爲到Server 2上。
下面分析一致性哈希算法的容錯性和可擴展性。現假設Server 3宕機了:
下面考慮另一種狀況,若是咱們在系統中增長一臺服務器Memcached Server 4:
綜上所述,一致性哈希算法對於節點的增減都只需重定位環空間中的一小部分數據,具備較好的容錯性和可擴展性。
一致性哈希算法在服務節點太少時,容易由於節點分部不均勻而形成數據傾斜問題。例如咱們的系統中有兩臺服務器,其環分佈以下: