[白話解析] 深刻淺出一致性Hash原理

[白話解析] 深刻淺出一致性Hash原理

0x00 摘要

一致性哈希算法是分佈式系統中經常使用的算法。但相信不少朋友都是知其然而不知其因此然。本文將盡可能使用易懂的方式介紹一致性哈希原理,而且經過具體應用場景來幫助你們深刻這個概念。html

0x01. 概念&原理

Hash,通常翻譯作散列、雜湊,或音譯爲哈希,是把任意長度的輸入(又叫作預映射pre-image)經過散列算法變換成固定長度的輸出,該輸出就是散列值。算法

一致性哈希算法在1997年由麻省理工學院的Karger等人在解決分佈式Cache中提出的,主要是爲了解決因特網中的熱點(Hot spot)問題。目前這一思想已經擴展到其它的領域,而且在實踐中獲得了很大的發展。服務器

1. 與經典哈希方法的對比

  • 經典哈希方法:老是假設內存位置的數量是已知且固定不變的。由於hash映射依賴節點/內存位置,因此若是須要變化集羣,須要從新計算每個key的哈希值。哈希表(服務器數量)大小的變動實際上干擾了 全部映射分佈式

  • 一致性哈希:某種虛擬環結構。位置數量再也不固定,環有無限數量的點,服務器節點能夠放置在環上的隨機位置。哈希表(服務器數量)大小改變會致使 只有 一部分請求(相對於環分配因子)會受到特定的環變動的影響函數

2. 通俗理解一致性哈希的關鍵點:

拗口的技術術語來解釋,一致性哈希的技術關鍵點是:按照經常使用的hash算法來將對應的key哈希到一個具備2^32次方個桶的空間中,即0 ~(2^32)-1的數字空間。咱們能夠將這些數字頭尾相連,想象成一個閉合的環形。spa

通俗白話來理解,這個關鍵點就是:在部署服務器的時候,服務器的序號空間已經配置成了一個固定的很是大的數字 1~2^32。服務器能夠分配爲 1~2^32 中任一序號。這樣服務器集羣能夠固定大多數算法規則 (由於序號空間是算法的重要參數),這樣面對擴容等變化只是對部分算法規則作調整。具體會參見後面實例詳細說明。.net

3. 一致性哈希如何處理請求

如何決定哪一個請求將由哪一個服務器節點來處理?翻譯

從理論上來講,每一個服務器節點「擁有」哈希環的一個區間,進入該區間的任何請求將由同一服務器節點來處理。htm

咱們假設環是有序的,以便環的順時針遍歷與位置地址的遞增順序對應,那麼每一個請求能夠由最早出如今該順時針遍歷中的那個服務器節點來處理。也就是說,地址高於請求地址的第一個服務器節點負責處理該請求。若是請求地址高於最高尋址節點,它由最小地址的服務器節點來處理,由於環遍歷以圓形方式進行。blog

4. 異常處理/變化應對

若是其中一個服務器節點出現故障,下一個服務器節點的區間就變寬,進入該區間的任何請求都將進入到新的服務器節點。這時候應該如何處理這些異常的請求?

一致性Hash的優點就在這裏體現:須要從新分配的是僅僅這一個區間(與出現故障的服務器節點對應),哈希環的其他部分和請求/節點分配仍然不受影響。

0x02. 具體應用場景(經過名著水滸傳爲例來闡釋)

你們都知道,梁山泊山下有四個酒店。分別是: 東山酒店 / 西山酒店 / 南山酒店 / 北山酒店

那麼這四個酒店如何分配客人入住呢? 這裏就能用到Hash算法,也能看到一致性哈希的好處。

1. 經典算法:

梁山4個酒店,按照順序其序號是1,2,3,4。

哈希函數:客人姓名筆畫 / 4獲得一個餘數,客人按照餘數分配到這4個酒店中

若是減小一個酒店,哈希函數就變成: 客人按照姓名筆畫 / 3,而後客人按照這個新餘數來分配酒店。全部客人都得從新分配酒店

若是增長一個酒店,哈希函數就變成: 客人按照姓名筆畫 / 5,而後客人按照這個新餘數來分配酒店。全部客人都得從新分配酒店

能夠看到,若是有容量變化,則哈希函數和分配規則都要改變,這樣就對總體機制形成了傷害。

2. 一致性算法:

預先就把服務器的序號空間(如今~將來)想好了,定爲100個桶。就是在將來可見的年分內,100個確定夠了(l梁山不管怎麼擴大生產規模,哪怕擴招了10000個頭領,山下也沒有開設100個酒店的可能)。

哈希函數(這個固定不變):

客人姓名筆畫/100. 這個是固定不變的! 由於100這個序號空間固定了,因此哈希函數和分配規則都基本固定了。

酒店/客人分配規則以下(這個會根據容量變化作相應微調):

  • 酒店1負責 hash(x)--> 1~20,即客人姓名筆畫/100位於1~20之間。

  • 酒店2負責 hash(x)--> 21~40,即客人姓名筆畫/100位於21~40之間。

  • 酒店3負責 hash(x)--> 41~60,即客人姓名筆畫/100位於41~60之間。

  • 酒店4負責 hash(x)--> 61~100,即客人姓名筆畫/100位於61~100之間。

客人住店規則以下(這個固定不變):

  • 客人來了,姓氏筆畫/100,獲得餘數。去餘數對應的酒店住。好比餘數3住到酒店1,餘數22則住到酒店2......

  • 若是該酒店出問題關門了,就去比全部 "比餘數大的酒店" 中最小那個住。以此類推。好比酒店1掛了,就去酒店2,酒店2掛了去3。

  • 若是最大酒店也出問題關門了,就轉圈回到最小酒店住。即若是酒店4掛了去酒店1.

異常處理(擴容或者宕機):

  • 減小酒店。若是酒店3掛了,則原來去酒店3的客人去酒店4,原來去酒店4的客人仍是酒店4. 這樣只有酒店4受到影響,1,2號酒店客人不用搬家。

  • 增長酒店。若是增長了一個酒店5.則須要對 酒店/客人分配規則 作改變。讓4號酒店負責61~80,5號酒店負責81~100。這樣4號點原有部分客人要遷移到5號。

關鍵點:

能夠看出來,關鍵在於服務器的序號空間早就肯定了是一個之後也不會修改的大數字100。固然這是梁山。對於其餘真實案例多是2^32。這樣hash函數 (由於序號空間是算法一個重要參數) 能夠保持不變,只有"分配規則" 須要根據實際系統容量作相應微調。從而對總體系統影響較小。

固然具體分配酒店的規則算法,是能夠融入到hash中。即酒店號碼可能就是21,41,61....

0x03. 參考

http://www.javashuo.com/article/p-aihsrxyr-cp.html

http://www.javashuo.com/article/p-dczpmtqp-mq.html

https://www.iteblog.com/archives/2499.html

http://www.zsythink.net/archives/1182/

https://www.sohu.com/a/239283928_463994

相關文章
相關標籤/搜索