日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

一致性 Hash 算法学习(分布式或均衡算法)

發(fā)布時(shí)間:2024/6/3 编程问答 44 豆豆
生活随笔 收集整理的這篇文章主要介紹了 一致性 Hash 算法学习(分布式或均衡算法) 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

簡介:

一致性哈希算法在1997年由麻省理工學(xué)院提出的一種分布式哈希(DHT)實(shí)現(xiàn)算法,設(shè)計(jì)目標(biāo)是為了解決因特網(wǎng)中的熱點(diǎn)(Hot spot)問題,初衷和CARP十分類似。一致性哈希修正了CARP使用的簡單哈希算法帶來的問題,使得分布式哈希(DHT)可以在P2P環(huán)境中真正得到應(yīng)用。

場(chǎng)景引入:

比如你有 N 個(gè) cache 服務(wù)器(后面簡稱 cache ),那么如何將一個(gè)對(duì)象 object 映射到 N 個(gè) cache 上呢,你很可能會(huì)采用類似下面的通用方法計(jì)算 object 的 hash 值,然后均勻的映射到到 N 個(gè) cache :

hash(object)%N

上面取模的方法一般稱為簡單 hash 算法 。通過簡單 hash 算法確實(shí)能夠比較均勻地實(shí)現(xiàn)分布式布置(映射),但是我們來考慮下面兩種情形:

1) 某個(gè) cache 服務(wù)器 m down 掉了(在實(shí)際應(yīng)用中必須要考慮這種情況),這樣所有映射到 cache m 的對(duì)象都會(huì)失效,怎么辦,需要把 cache m 從 cache 中移除,這時(shí)候 cache 是 N-1 臺(tái),映射公式變成了 hash(object)%(N-1) ;

2) 由于訪問加重,需要添加 cache ,這時(shí)候 cache 是 N+1 臺(tái),映射公式變成了 hash(object)%(N+1) ;

1) 和 2) 意味著什么?這意味著無論是添加或移除 cache 服務(wù)器,突然之間幾乎所有的 cache 都失效了。對(duì)于服務(wù)器而言,這是一場(chǎng)災(zāi)難,洪水般的訪問都會(huì)直接沖向后臺(tái)服務(wù)器;

為了解決上面的問題,我們引入一致性 Hash 算法(consistent hashing)。

hash 算法和單調(diào)性

Hash 算法的一個(gè)衡量指標(biāo)是單調(diào)性( Monotonicity ),定義如下:

  單調(diào)性是指如果已經(jīng)有一些內(nèi)容通過哈希分派到了相應(yīng)的緩沖中,又有新的緩沖加入到系統(tǒng)中。哈希的結(jié)果應(yīng)能夠保證原有已分配的內(nèi)容可以被映射到新的緩沖中去,而不會(huì)被映射到舊的緩沖集合中的其他緩沖區(qū)。

簡單的說,單調(diào)性要求在移除 / 添加一個(gè) cache(機(jī)器,ip)時(shí),它能夠盡可能小的改變已存在 key 映射關(guān)系。

容易看到,上面的簡單 hash 算法 hash(object)%N 難以滿足單調(diào)性要求。因?yàn)?N 的變化會(huì)使取模結(jié)果發(fā)生變化。

一致性 Hash 算法原理:

一致性 Hash 算法簡單的說,在移除 / 添加一個(gè) cache 時(shí),它能夠盡可能小的改變已存在 key 映射關(guān)系,盡可能的滿足單調(diào)性的要求。

下面就來按照 6 個(gè)步驟簡單講講一致性 Hash 算法的基本原理。

步驟一:環(huán)形 hash 空間

考慮通常的 hash 算法都是將 value 映射到一個(gè) 32 位的 key 值(然后取模),也即是 0~2^32-1 次方的數(shù)值空間;我們可以將這個(gè)空間想象成一個(gè)首( 0 )尾( 2^32-1 )相接的圓環(huán)。如下圖所示:

步驟二:把對(duì)象處理成整數(shù)并映射到環(huán)形 hash 空間

例如現(xiàn)在我們有四個(gè)對(duì)象 object1~object4,通過 hash 函數(shù)將四個(gè)對(duì)象處理成整數(shù) key:

key1 = hash(object1);?
key2 = hash(object2);?
key3 = hash(object3);?
key4 = hash(object4);

然后將這些對(duì)象按照 key 的值映射到環(huán)形 hash 空間上:

步驟三:把 cache 映射到環(huán)形 hash 空間

一致性 Hash 算法的基本思想就是將對(duì)象和 cache 都映射到同一個(gè) hash 數(shù)值空間中,并且使用相同的 hash 算法。

假設(shè)現(xiàn)在有三臺(tái) cache 服務(wù)器:cacheA、cacheB、cacheC,通過 hash 函數(shù)處理獲取對(duì)應(yīng)的key值:

keyA = hash(cacheA);?
keyB = hash(cacheB);?
keyC = hash(cacheC);

將三個(gè) cache 服務(wù)器按照 key 的值映射到環(huán)形 hash 空間上:

說到這里,順便提一下 cache 的 hash 計(jì)算,一般的方法可以使用 cache 機(jī)器的 IP 地址或者機(jī)器名作為 hash 輸入。

經(jīng)過上面的步驟,我們把對(duì)象和cache 服務(wù)器都映射到同一個(gè)環(huán)形 hash 空間上。下面考慮的是如何將對(duì)象映射到 cache 服務(wù)器上。

步驟四:將對(duì)象映射到 cache 服務(wù)器

我們沿著圓環(huán)順時(shí)針方向的對(duì)象 key (圖中的 key1)出發(fā),直到遇到一個(gè)cache服務(wù)器為止(cacheB),把對(duì)象key對(duì)應(yīng)的對(duì)象映射到這個(gè)服務(wù)器上。因?yàn)閷?duì)象和 cache 的 hash 值是固定的,因此這個(gè) cache 必然是唯一和確定的。按照這樣的方法,可以得出:對(duì)象 object 1 映射到 cacheB,object2、object3 映射到 cacheC,object4 映射到 cacheA。如圖:

前面講過,普通 hash 算法(通過 hash 然后求余的方法)帶來的最大問題就在于不能滿足單調(diào)性,當(dāng) cache 數(shù)量有所變動(dòng)時(shí)(添加/移除), 幾乎所有的 cache 會(huì)失效,進(jìn)而對(duì)后臺(tái)服務(wù)器造成巨大的沖擊,接下來分析一致 hash 算法。

步驟五:添加 cache 服務(wù)器

現(xiàn)在假如訪問加重,需要增加 cacheD 服務(wù)器,經(jīng)過 hash 函數(shù)計(jì)算(keyD = hash(cacheD))發(fā)現(xiàn)數(shù)值介于 key3 和 key2 之間,即在圓環(huán)上的位置也是介于它們之間。這時(shí)候受到影響的是沿著 KeyD 逆時(shí)針出發(fā)直到遇到下一個(gè) cache 服務(wù)器(keyB)之間的對(duì)象(這些對(duì)象原本是映射到 cacheC 上的),將這些對(duì)象重新映射到 cacheD 即可。

在我們的例子中僅僅是 object2(key2)需要變動(dòng),將其重新映射到 cacheD 即可:

步驟六:移除 cache 服務(wù)器

還是按照原來的圖(步驟五之前)分析,假如現(xiàn)在 cacheB 服務(wù)器 down 掉了,需要把 cacheB 服務(wù)器移除,這時(shí)候受到影響的僅是那些沿著 keyB 逆時(shí)針出發(fā)知道遇到下一個(gè)服務(wù)器(cacheA)之間的對(duì)象,也就是本來映射到 cacheB 上的那些對(duì)象。

我們的例子中僅僅是 object1(key1)需要變動(dòng),將其重新映射到 cacheC 即可:

平衡性與虛擬節(jié)點(diǎn):

考量 Hash 算法的另一個(gè)指標(biāo)是平衡性 (Balance) ,定義如下:

平衡性

  平衡性是指哈希的結(jié)果能夠盡可能分布到所有的緩沖中去,這樣可以使得所有的緩沖空間都得到利用。

hash 算法并不是保證絕對(duì)的平衡,如果 cache 較少的話,對(duì)象并不能被均勻的映射到 cache 上,比如在上面的例子中,僅部署 cache A 和 cache C 的情況下,在 4 個(gè)對(duì)象中, cache A 僅存儲(chǔ)了 object1 ,而 cache C 則存儲(chǔ)了 object2 、 object3 和 object4 ;分布是很不均衡的。

為了解決這種情況, 一致性 Hash 算法引入了“虛擬節(jié)點(diǎn)”的概念,它可以如下定義:

虛擬節(jié)點(diǎn)

“虛擬節(jié)點(diǎn)”( virtual node )是實(shí)際節(jié)點(diǎn)在 hash 空間的復(fù)制品( replica ),一實(shí)際個(gè)節(jié)點(diǎn)對(duì)應(yīng)了若干個(gè)“虛擬節(jié)點(diǎn)”,這個(gè)對(duì)應(yīng)個(gè)數(shù)也成為“復(fù)制個(gè)數(shù)”,“虛擬節(jié)點(diǎn)”在 hash 空間中以 hash 值排列。

仍以僅部署 cache A 和 cache C 的情況為例,在移除 cacheB 服務(wù)器圖中我們已經(jīng)看到, cache 分布并不均勻。現(xiàn)在我們引入虛擬節(jié)點(diǎn),并設(shè)置“復(fù)制個(gè)數(shù)”為 2 ,這就意味著一共會(huì)存在 4 個(gè)“虛擬節(jié)點(diǎn)”, cache A1, cache A2 代表了 cache A ; cache C1, cache C2 代表了 cache C ;假設(shè)一種比較理想的情況,如圖:

此時(shí),對(duì)象到“虛擬節(jié)點(diǎn)”的映射關(guān)系為:

objec1->cache C2 ; objec2->cache A1 ; objec3->cache C1 ; objec4->cache A2 ;

因此對(duì)象 object4 和 object2 都被映射到了 cache A 上,而 object3 和 object1 映射到了 cache C 上;平衡性有了很大提高。

引入“虛擬節(jié)點(diǎn)”后,映射關(guān)系就從 { 對(duì)象 -> 節(jié)點(diǎn) } 轉(zhuǎn)換到了 { 對(duì)象 -> 虛擬節(jié)點(diǎn) } 。查詢物體所在 cache 時(shí)的映射關(guān)系如圖所示。

“虛擬節(jié)點(diǎn)”的 hash 計(jì)算可以采用對(duì)應(yīng)節(jié)點(diǎn)的 IP 地址加數(shù)字后綴的方式。例如假設(shè) cache A 的 IP 地址為 202.168.14.241 。

引入“虛擬節(jié)點(diǎn)”前,計(jì)算 cache A 的 hash 值:

Hash(“202.168.14.241”);

引入“虛擬節(jié)點(diǎn)”后,計(jì)算“虛擬節(jié)”點(diǎn) cache A1 和 cache A2 的 hash 值:

Hash(“202.168.14.241#1”); // cache A1

Hash(“202.168.14.241#2”); // cache A2

一個(gè)PHP的例子:

<?php class FlexiHash{private $serverList = array(); //服務(wù)器列表private $isSorted = false; //服務(wù)器列表是否已經(jīng)排過序//hash函數(shù)function mhash($key){$md5 = substr(md5($key)0,8);$seed = 31;$hash = 0;for($i = 0;$i < 8;$i ++){$hash = $hash * $seed + ord($md5{$i});}return $hash & 0x7FFFFFFF;}//添加服務(wù)器function addServer($server){$hash = $this->mhash($server);if(!isset($this->serverList[$hash])){$this->serverList[$hash] = $server;}$this->isSorted = false;return true;}//移除服務(wù)器function removeServer($server){$hash = $this->mhash($server);if(isset($this->serverList[$hash])){unset($this->serverList[$hash]);}$this->isSorted = false;return true;}//查找映射服務(wù)器(算法實(shí)現(xiàn)函數(shù))function lookup($key){$hash = $this->mhash($key);if(!$this->isSorted){krsort($this->serverList,SORT_NUMERIC);$this->isSorted = true;}foreach($this->serverList as $pos => $server){if($hash >= $pos){return $server;}}return reset($this->serverList); //返回第一個(gè)元素} }

上面僅是一個(gè)簡單的實(shí)現(xiàn)一致性 Hash 算法的例子,并沒有考慮虛擬節(jié)點(diǎn),有興趣的同學(xué)可以試試。

本篇博客參考自http://blog.csdn.net/sparkliang/article/details/5279393和書本《PHP核心技術(shù)與最佳算法》

與50位技術(shù)專家面對(duì)面20年技術(shù)見證,附贈(zèng)技術(shù)全景圖

總結(jié)

以上是生活随笔為你收集整理的一致性 Hash 算法学习(分布式或均衡算法)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。