一文搞懂一致性hash的原理和實現(xiàn)

在 go-zero 的分布式緩存系統(tǒng)分享里屁药,Kevin 重點講到過一致性hash的原理和分布式緩存中的實踐轴捎。本文來詳細講講一致性hash的原理和在 go-zero 中的實現(xiàn)憋他。

以存儲為例进陡,在整個微服務(wù)系統(tǒng)中释牺,我們的存儲不可能說只是一個單節(jié)點萝衩。

  • 一是為了提高穩(wěn)定,單節(jié)點宕機情況下没咙,整個存儲就面臨服務(wù)不可用猩谊;
  • 二是數(shù)據(jù)容錯,同樣單節(jié)點數(shù)據(jù)物理損毀祭刚,而多節(jié)點情況下牌捷,節(jié)點有備份,除非互為備份的節(jié)點同時損毀涡驮。

那么問題來了宜鸯,多節(jié)點情況下,數(shù)據(jù)應(yīng)該寫入哪個節(jié)點呢遮怜?

hash

image

所以本質(zhì)來講:我們需要一個可以將輸入值“壓縮”并轉(zhuǎn)成更小的值淋袖,這個值通常狀況下是唯一、格式極其緊湊的锯梁,比如uint64

  • 冪等:每次用同一個值去計算 hash 必須保證都能得到同一個值

這個就是 hash 算法完成的即碗。

但是采取普通的 hash 算法進行路由,如:key % N 陌凳。有一個節(jié)點由于異常退出了集群或者是心跳異常剥懒,這時再進行 hash route ,會造成大量的數(shù)據(jù)重新 分發(fā)到不同的節(jié)點 合敦。節(jié)點在接受新的請求時候初橘,需要重新處理獲取數(shù)據(jù)的邏輯:如果是在緩存中,容易引起 緩存雪崩

此時就需要引入 consistent hash 算法了保檐。

consistent hash

我們來看看 consistent hash 是怎么解決這些問題的:

rehash

先解決大量 rehash 的問題:

image

如上圖耕蝉,當(dāng)加入一個新的節(jié)點時,影響的key只有 key31夜只,新加入(剔除)節(jié)點后垒在,只會影響該節(jié)點附近的數(shù)據(jù)。其他節(jié)點的數(shù)據(jù)不會收到影響扔亥,從而解決了節(jié)點變化的問題场躯。

這個正是:單調(diào)性。這也是 normal hash 算法無法滿足分布式場景的原因旅挤。

數(shù)據(jù)傾斜

其實上圖可以看出:目前多數(shù)的key都集中在 node 1 上踢关。如果當(dāng) node 數(shù)量比較少的情況下,可以回引發(fā)多數(shù) key 集中在某個 node 上粘茄,監(jiān)控時發(fā)現(xiàn)的問題就是:節(jié)點之間負載不均耘成。

為了解決這個問題,consistent hash 引入了 virtual node 的概念驹闰。

既然是負載不均,我們就人為地構(gòu)造一個均衡的場景出來撒会,但是實際 node 只有這么多嘹朗。所以就使用 virtual node 劃分區(qū)域,而實際服務(wù)的節(jié)點依然是之前的 node诵肛。

具體實現(xiàn)

先來看看 Get()

Get

image

先說說實現(xiàn)的原理:

  1. 計算 key 的hash
  2. 找到第一個匹配的 virtual node 的 index屹培,并取到對應(yīng)的 h.keys[index] :virtual node hash 值
  3. 對應(yīng)到這個 ring 中去尋找一個與之匹配的 actual node

其實我們可以看到 ring 中獲取到的是一個 []node 。這是因為在計算 virtual node hash 怔檩,可能會發(fā)生hash沖突褪秀,不同的 virtual node hash 對應(yīng)到一個實際node。

這也說明:nodevirtual node 是一對多的關(guān)系薛训。而里面的 ring 就是下面這個設(shè)計:

image

這個其實也就表明了一致性hash的分配策略:

  1. virtual node 作為值域劃分媒吗。key 去獲取 node ,從劃分依據(jù)上是以 virtual node 作為邊界
  2. virtual node 通過 hash 乙埃,在對應(yīng)關(guān)系上保證了不同的 node 分配的key是大致均勻的闸英。也就是 打散綁定
  3. 加入一個新的 node,會對應(yīng)分配多個 virtual node介袜。新節(jié)點可以負載多個原有節(jié)點的壓力甫何,從全局看,較容易實現(xiàn)擴容時的負載均衡遇伞。

Add Node

image

看完 Get 其實大致就知道整個一致性hash的設(shè)計:

type ConsistentHash struct {
  hashFunc Func                         // hash 函數(shù)
  replicas int                          // 虛擬節(jié)點放大因子
  keys     []uint64                 // 存儲虛擬節(jié)點hash
  ring     map[uint64][]interface{}                 // 虛擬節(jié)點與實際node的對應(yīng)關(guān)系
  nodes    map[string]lang.PlaceholderType  // 實際節(jié)點存儲【便于快速查找辙喂,所以使用map】
  lock     sync.RWMutex
}

好了這樣,基本的一個一致性hash就實現(xiàn)完備了。

具體代碼:https://github.com/tal-tech/go-zero/blob/master/core/hash/consistenthash.go

使用場景

開頭其實就說了巍耗,一致性hash可以廣泛使用在分布式系統(tǒng)中:

  1. 分布式緩存秋麸。可以在 redis cluster 這種存儲系統(tǒng)上構(gòu)建一個 cache proxy芍锦,自由控制路由竹勉。而這個路由規(guī)則就可以使用一致性hash算法
  2. 服務(wù)發(fā)現(xiàn)
  3. 分布式調(diào)度任務(wù)

以上這些分布式系統(tǒng)中,都可以在負載均衡模塊中使用娄琉。

項目地址

https://github.com/tal-tech/go-zero

歡迎使用 go-zero 并 star 支持我們次乓!

微信交流群

關(guān)注『微服務(wù)實踐』公眾號并點擊 交流群 獲取社區(qū)群二維碼。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末孽水,一起剝皮案震驚了整個濱河市票腰,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌女气,老刑警劉巖杏慰,帶你破解...
    沈念sama閱讀 216,372評論 6 498
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異炼鞠,居然都是意外死亡缘滥,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,368評論 3 392
  • 文/潘曉璐 我一進店門谒主,熙熙樓的掌柜王于貴愁眉苦臉地迎上來朝扼,“玉大人,你說我怎么就攤上這事霎肯∏嬗保” “怎么了?”我有些...
    開封第一講書人閱讀 162,415評論 0 353
  • 文/不壞的土叔 我叫張陵观游,是天一觀的道長搂捧。 經(jīng)常有香客問我,道長懂缕,這世上最難降的妖魔是什么允跑? 我笑而不...
    開封第一講書人閱讀 58,157評論 1 292
  • 正文 為了忘掉前任,我火速辦了婚禮搪柑,結(jié)果婚禮上吮蛹,老公的妹妹穿的比我還像新娘。我一直安慰自己拌屏,他們只是感情好潮针,可當(dāng)我...
    茶點故事閱讀 67,171評論 6 388
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著倚喂,像睡著了一般每篷。 火紅的嫁衣襯著肌膚如雪瓣戚。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,125評論 1 297
  • 那天焦读,我揣著相機與錄音子库,去河邊找鬼。 笑死矗晃,一個胖子當(dāng)著我的面吹牛仑嗅,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播张症,決...
    沈念sama閱讀 40,028評論 3 417
  • 文/蒼蘭香墨 我猛地睜開眼仓技,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了俗他?” 一聲冷哼從身側(cè)響起脖捻,我...
    開封第一講書人閱讀 38,887評論 0 274
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎兆衅,沒想到半個月后地沮,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,310評論 1 310
  • 正文 獨居荒郊野嶺守林人離奇死亡羡亩,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,533評論 2 332
  • 正文 我和宋清朗相戀三年摩疑,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片畏铆。...
    茶點故事閱讀 39,690評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡雷袋,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出及志,到底是詐尸還是另有隱情,我是刑警寧澤寨腔,帶...
    沈念sama閱讀 35,411評論 5 343
  • 正文 年R本政府宣布速侈,位于F島的核電站,受9級特大地震影響迫卢,放射性物質(zhì)發(fā)生泄漏倚搬。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,004評論 3 325
  • 文/蒙蒙 一乾蛤、第九天 我趴在偏房一處隱蔽的房頂上張望每界。 院中可真熱鬧,春花似錦家卖、人聲如沸眨层。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,659評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽趴樱。三九已至馒闷,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間叁征,已是汗流浹背纳账。 一陣腳步聲響...
    開封第一講書人閱讀 32,812評論 1 268
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留捺疼,地道東北人疏虫。 一個月前我還...
    沈念sama閱讀 47,693評論 2 368
  • 正文 我出身青樓,卻偏偏與公主長得像啤呼,于是被迫代替她去往敵國和親卧秘。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,577評論 2 353

推薦閱讀更多精彩內(nèi)容