一致性雜湊

2021-09-24 15:13:03 字數 3253 閱讀 2433

先介紹乙個經典的伺服器結構,有乙個前端,前端伺服器組可能就是專門用來分發用的,比如乙個請求,舉乙個具體的例子,比如乙個request,查乙個姓名叫「zuo」的告訴年齡age是多少。這個往伺服器上存的時候實際上推的是這麼乙個對兒,,也可以更新它,也可以拿出,「zuo」作為key,31作為value。乙個經典的結構包括乙個更複雜的request也是這樣的:請求先到達前端伺服器,前端伺服器的某一台(這些分發伺服器是無差別的,打到哪個上面都給提供相同的服務)。比如說乙個網域名稱,google.com,這個網域名稱下面可能有一大堆機器,reques先通過dns走一圈,來到具體某個公司的request上,前端收到請求後會打到後端伺服器組,後端伺服器組就有講究了,我可以認為任何乙個request過來之後都會打到某一台前端伺服器上,這個時候是無差別的,打到哪個伺服器上提供的都是相同的服務。提供的服務是,(比如後端伺服器有三颱機器)通過key計算一下雜湊得到乙個雜湊的返回值,hashvalue。把這個hashvalue%3,結果只可能是0,1,2。如果是0,就去0號機器上拿,如果是1,就去1號機器上拿,如果是2,就去2號機器上拿。如果想把這個資訊加入怎麼加?先看這個請求的key是什麼,打到0號機器還是1號機器還是2號機器,打到某台機器上加上這個資訊。從中拿也是這麼拿。由於雜湊函式是非常均衡的,如果有很多字串作為key的話,會負載均衡的分布在0,1,2機器上。這是乙個經典的伺服器負載結構。而且超級負載均衡。我們知道乙個雜湊值很高,模上3之後得到0或1或2的次數也基本是相同的,概率上是差不多的,當然它不是乙個隨機函式,但知道是啥意思就行了。

這是個經典的伺服器結構,之前大家都是這麼做的,被大量使用,後來發現不好,因為當台數固定的時候是沒什麼問題的,但如果加一台呢,原來模3現在則應該模4,想讓它繼續負載均衡的話,得把0機器1機器2機器的所有的key拿出來重新計算一遍雜湊,重新模4。比如0機器上的訊息,具體乙個key應該把它分到哪去呢,就得重新算一遍,所以加機器減機器的時候就不行了,改**還是其次,問題是資料遷移的代價太高了。把所有資料的key拿出來重新取雜湊再模4,才能得到資料新的歸屬在這4臺機器的哪一台,所以這是乙個問題。而一致性雜湊這個結構可以幫助解決這個問題。

而一致性雜湊是個什麼結構呢?前端是無差別的,也可以認為每乙個request打到前端所提供的服務是一樣的,就是告訴它到後端的哪一台上去。前端沒有任何變化。原來的0號桶,1號桶,2號桶是固定的,而一致性雜湊結構不是這樣的,hash函式的輸入是任意乙個字串,字串的數量是很多的,可以認為是無窮大的乙個量級,雜湊的返回值假設是0到2的64次方的範圍。那麼一致性雜湊的結構,就可以把整個雜湊域想象成乙個環,0號位置的下乙個位置就是1號位置,再下乙個位置就是2號位置,轉一圈到2的64次方位置,2的64次方的下乙個位置是0號位置,這個環是首尾相接的,在這種結構下,先別管前端伺服器,先看後端的。假設有三颱機器,m1,m2,m3,後端這三颱機器肯定有專屬於每台機器的資訊,比如說m1,m2和m3的ip肯定就不一樣,mac位址肯定就不一樣,hostname肯定也不一樣,這些不一樣的資訊假設是ip,那麼m1就有個ip1,m2就有個ip2,m3就有個ip3,反正肯定不一樣。把m1的ip1通過雜湊函式算出乙個雜湊值,打到環上去;把m2的ip2通過雜湊函式算出乙個雜湊值,打到環上去;把m3的ip3通過雜湊函式算出乙個雜湊值,打到環上去;假設打到環上的不同三個位置。當乙個request從前端伺服器組到來的時候,前端算出乙個雜湊值,記為hash_request1,這個雜湊值肯定對應環上某個位置,假設打到m1和m2之間的乙個位置,那麼request去哪台機器上處理請求呢,去順時針遇到的第一台機器。

在實踐過程中,其實很好做,m1,m2,m3各自算出的雜湊值h1,h2,h3將其排序,假設排序後是【16,120億,1024億】這樣三個雜湊值,把排序後每乙個陣列放到前端**伺服器裡。每個**伺服器都存著乙個有序陣列,伺服器端有幾台機器,這個陣列就有多少個值。而且是排序之後的。那麼乙個request到來之後怎麼順時針的找,假設前端伺服器拿到乙個request算出乙個雜湊值是1023億,其實就是在這個有序陣列中二分的找剛好比它大的雜湊值。那麼就找到了1024億。那麼就去1024億這個雜湊值代表的機器上去處理這個請求。如果是1025億,沒有比它剛剛好大的值,那就應該順著環去16這個雜湊值代表的機器。

前端搞定了看後端,在這種情況下要是想加一台機器就很容易,資料遷移代價就很小,比如要加一台m4,m4算出雜湊值h4,打到環上的某個位置上,m4要進這個環要做什麼操作呢?首先m4算出的雜湊值應該在前端伺服器的有序陣列裡面加上它,所以在後端伺服器要做的操作就是,m4上了乙個環,只用找到m4順時針的第一台機器,即m3,把原本m3負責的某一段資料傳給m4,m3刪掉那些資料,m4留著就行了。以後這一部分的資料就m4處理了。其實就是m3的某部分資料拿給m4就可以了,剩下的都不用變,這就是加機器的時候進行的資料遷移的代價,是很低的。

同理原來是四台機器想要刪掉一台m4要怎麼刪呢,就把m4上所有的資料給到m3就可以了,可見減機器的時候也很方便。

但問題在於:1.雜湊函式只有在量起來的時候,雜湊函式的特徵才能起來,如果一開始就是三颱機器或者兩台機器,初始機器數量很少的時候,就不能保證整個環被均分。因為它是個離散函式,可能兩個點在環上打的特別近,不保證一定能打到對側均分這樣。而環不均也就意味著機器負載不均衡了。

2.即便能夠解決第乙個問題,在兩台或者三颱的時候假如你用某種魔幻的方式做到了把環均分,那加機器的時候也照樣會破壞均衡性。

這兩個問題是雜湊函式的性質帶來的。如果乙個房間只給你有限個香水分子那它們分布肯定是不均勻的,但是香水量大了之後就能保證均勻了,基本上你在房間的任何乙個角落聞到香水的濃度應該都是差不多的。也就是說,雜湊函式的性質使得少量的時候不保證均衡,即便保證均衡了,加台機器又不均衡了。

這兩個問題用虛擬節點技術可以解決。假設有三颱機器,m1,m2,m3,還是去搶乙個環,但方式變了。假設m1這台機器,不讓物理機去搶這個環,而是給它分配一萬個虛擬節點,v1-1,v1-2,v1-3...v1-10000,這是一張路由表,通過m1可以查有哪些虛擬節點,通過乙個虛擬節點可以查它屬於哪個物理機器。m2,同理,m3同理都分別分配一萬個虛擬節點,然後讓這三萬個虛擬節點去搶這個環,v1-1到v1-10000的每個虛擬節點負責的域都歸在m1上。m2,同理,m3同理。那麼m1,m2,m3就把環均分了。因為量起來了很大,有三萬個節點。

再說一下工程落地,m1怎麼分10000個虛擬節點呢?我們總能拿到一些專屬資訊。比如m1的ip位址196.125.1.1,就把196.125.1.1-1算出乙個雜湊值就作為虛擬節點v1-1的雜湊值,196.125.1.1-2算出乙個雜湊值就作為虛擬節點v1-2的雜湊值,一直到196.125.1.1-10000算出乙個雜湊值就作為虛擬節點v1-10000的雜湊值。

有了虛擬節點技術,初始機器量少以及加減機器的問題全部解決了。這個技術有應用到很多地方,只要任何乙個有分布式系統有伺服器概念的地方都被它改造過,亞馬遜的dynamodb就是用這個做的。spark有一些服務也是用這個技術做的。只要是牽涉到分布式要共同負載的東西,一致性雜湊用到了很多。

一致性雜湊

直接貼出一篇介紹的很清楚的博文。關鍵字一致性雜湊 平衡性,單調性,分散性,負載 其實說白了,就是解決把請求分散到不同的機器上運算,怎麼做分散的平均,機器少一台多一台,或者壞掉一台,成很好的自適應和拓展。最簡單的實現分布式演算法,取模嘛,但是它就上述的一些問題,所以不算好的雜湊函式。一致性雜湊演算法,...

一致性雜湊

from 學習分布式,一致性雜湊是最最基礎的知識,所以要理解好.那什麼是一致性雜湊呢?what 1.平衡性是指 hash的結果應該平均分配到各個節點,這樣從演算法上就解決了負載均衡問題.2.單調性是指 在新增或者刪減節點時,同乙個key訪問到的值總是一樣的.3.分散性是指 資料應該分散的存放在 分布...

一致性雜湊

一致性 雜湊演算法在1997年由 麻省理工學院提出 參見擴充套件閱讀 1 設計目標是為了解決網際網路中的熱點 hot spot 問題,初衷和 carp十分類似。一致性雜湊修正了carp使用的簡單雜湊演算法帶來的問題,使得dht可以在p2p環境中真正得到應用。雜湊演算法 編輯 一致性雜湊提出了在動態變...