一致性雜湊演算法與C 實現

2021-07-11 16:55:15 字數 3791 閱讀 4469

一致性雜湊演算法在2023年由麻省理工學院提出的一種分布式雜湊(dht)實現演算法,設計目標是為了解決網際網路中的熱點(hot spot)問題,初衷和carp十分類似。一致性雜湊修正了carp使用的簡 單雜湊演算法帶來的問題,使得分布式雜湊(dht)可以在p2p環境中真正得到應用。

一致性hash演算法提出了在動態變化的cache環境中,判定雜湊演算法好壞的四個定義:

1、平衡性(balance):平衡性是指雜湊的結果能夠盡可能分布到所有的緩衝中去,這樣可以使得所有的緩衝空間都得到利用。很多雜湊演算法都能夠滿足這一條件。

2、單調性(monotonicity):單調性是指如果已經有一些內容通過雜湊分派到了相應的緩衝中,又有新的緩衝加入到系統中。雜湊的結果應能夠保證原有已分配的內容可以被對映到原有的或者新的緩衝中去,而不會被對映到舊的緩衝集合中的其他緩衝區。

3、分散性(spread):在分布式環境中,終端有可能看不到所有的緩衝,而是只能看到其中的一部分。當終端希望通過雜湊過程將內容對映到緩衝上時,由於不同終端所見的緩衝範圍有可能不同,從而導致雜湊的結果不一致,最終的結果是相同的內容被不同的終端對映到不同的緩衝區中。這種情況顯然是應該避免的,因為它導致相同內容被儲存到不同緩衝中去,降低了系統儲存的效率。分散性的定義就是上述情況發生的嚴重程度。好的雜湊演算法應能夠盡量避免不一致的情況發生,也就是盡量降低分散性。

4、負載(load):負載問題實際上是從另乙個角度看待分散性問題。既然不同的終端可能將相同的內容對映到不同的緩衝區中,那麼對於乙個特定的緩衝區而言,也可能被不同的使用者對映為不同 的內容。與分散性一樣,這種情況也是應當避免的,因此好的雜湊演算法應能夠盡量降低緩衝的負荷。

在分布式集群中,對機器的新增刪除,或者機器故障後自動脫離集群這些操作是分布式集群管理最基本的功能。如果採用常用的hash(object)%n演算法,那麼在有機器新增或者刪除後,很多原有的資料就無法找到了,這樣嚴重的違反了單調性原則。接下來主要講解一下一致性雜湊演算法是如何設計的。

把資料用hash函式(如md5,murmurhash等演算法),對映到乙個很大的空間裡,如圖所示。資料的儲存時,先得到乙個hash值,對應到這個環中的每個位置,如k1對應到了圖中所示的位置,然後沿順時針找到乙個機器節點b,將k1儲存到b這個節點中。

如果b節點宕機了,則b上的資料就會落到c節點上,如下圖所示:

這樣,只會影響c節點,對其他的節點a,d的資料不會造成影響。然而,這又會造成乙個「雪崩」的情況,即c節點由於承擔了b節點的資料,所以c節點的負載會變高,c節點很容易也宕機,這樣依次下去,這樣造成整個集群都掛了。

為此,引入了「虛擬節點」的概念:即把想象在這個環上有很多「虛擬節點」,資料的儲存是沿著環的順時針方向找乙個虛擬節點,每個虛擬節點都會關聯到乙個真實節點,如下圖所使用:

圖中的a1、a2、b1、b2、c1、c2、d1、d2都是虛擬節點,機器a負載儲存a1、a2的資料,機器b負載儲存b1、b2的資料,機器c負載儲存c1、c2的資料。由於這些虛擬節點數量很多,均勻分布,因此不會造成「雪崩」現象。

murmurhash演算法,是非加密hash演算法,效能很高, 比傳統的crc32, md5,sha-1(這兩個演算法都是加密hash演算法,複雜度本身就很高,帶來的效能上的損害也不可避免) 等hash演算法要快很多,而且這個演算法的碰撞率很低。所以這裡我們採用murmurhash演算法

標頭檔案consistent_hash.h

#include 

using

namespace

std;

class consistenthash

;

實現檔案consistent_hash.cpp

#include 

#include

#include

#include "consistent_hash.h"

#include "murmurhash3.h"

using

namespace

std;

consistenthash::consistenthash(int node_num, int virtual_node_num)

consistenthash::~consistenthash()

void consistenthash::initialize()

}}size_t consistenthash::getserverindex(const

char* key)

return it->second;

}void consistenthash::deletenode(const

int index)

}}void consistenthash::addnewnode(const

int index)

}

全部源**:

假設有10000個樣本,10種測試值(0-9)。

一致性雜湊中真實節點有5個(index是0-4),每個節點關聯100個虛擬節點。

測試結果如下:

consistent hash initialize success, node_num=5, virtual_num=100

key = 4, index = 3

key = 7, index = 3

key = 0, index = 3

key = 1, index = 3

key = 6, index = 3

key = 3, index = 3

key = 5, index = 0

key = 2, index = 4

key = 8, index = 2

key = 9, index = 0

node error,index = 3

key = 3, index = 4

key = 7, index = 2

key = 4, index = 1

key = 0, index = 2

key = 1, index = 1

key = 6, index = 4

node recover,index = 3

key = 4, index = 3

key = 3, index = 3

key = 0, index = 3

key = 1, index = 3

key = 7, index = 3

key = 6, index = 3

index = 0, data_count = 5985

index = 1, data_count = 1991

index = 2, data_count = 5041

index = 3, data_count = 12014

index = 4, data_count = 4969

測試了3次,每次10000個樣本;

第二次測試時,節點3壞了,導致原來儲存在節點3的資料(0,1,3,4,6,7)都被分配到了其他節點,但並不是全部都到某個節點上,防止了雪崩

第三次測試時,節點3恢復了,原來在節點3上的資料又恢復到3上了。

一致性雜湊演算法

好吧,我們決定打破這種基於資料項商業邏輯的劃分思維,來考慮一種基於 key 的劃分方式,這有些類似於後面介紹的資料庫水平分割槽 sharding 我們需要設計一種不依賴資料項內容的雜湊演算法,將所有資料項的 key 均衡分配在這三颱快取伺服器上。乙個簡單而有效的方法是 取餘 運算,這就像打撲克時的發...

一致性雜湊演算法

在分布式系統中,如果某業務可以由多個相同的節點處理,很容易想到用hash的方式將業務請求分散到這些節點處理,如果有n個節點,計算方法為 hash id n。如果只是簡單的計算,不涉及使用者狀態,這是乙個簡單有效的方案。如果節點的計算涉及使用者狀態,比如維護購物車 memcache快取服務等,好像也沒...

一致性雜湊演算法

判定好壞的四個定義 1 平衡性 balance 平衡性是指雜湊的結果能夠盡可能分布到所有的緩衝中去,這樣可以使得所有的緩衝空間都得到利用。很多雜湊演算法都能夠滿足這一條件。2 單調性 monotonicity 單調性是指如果已經有一些內容通過雜湊分派到了相應的緩衝中,又有新的緩衝加入到系統中。雜湊的...