redis之分布式算法原理

????本文主要會圍繞,redis分布式算法的原理以及環境配置搭建,和服務端客戶端啟動。我們會封裝一個分布式Shard Redis API,最后驗證一下Redis分布式環境驗證。另外會解釋一下,集群和分布式的概念。 ? (參考慕課geely課程:

來一波地址:https://coding.imooc.com/learn/list/162.html)?

? ? 一、分布式算法原理

? ? 1.1傳統的分布式算法.

? ??原始的做法是對緩存項的鍵進行哈希,將hash后的結果對緩存服務器的數量進行取模操作,通過取模后的結果,決定緩存項將會緩存在哪一臺服務器上。例如一個圖片選擇存哪臺服務器的一個過程,


傳統的分布式算法

? ? 這樣Hash取模的方式是有弊端的,就是在我們業務擴展的時候,新增服務器節點,會導致一部分數據不能準確的在緩存服務器中找到。換句話說,當服務器數量發生變化的時候,所有緩存在一點時間內是失效的,當應用無法從緩存中獲取數據時,則會向后端服務器請求數據,造成了緩存的雪崩,整個系統很有可能被壓垮,所以,我們應該想辦法不讓這種糟糕的情況出現,但是由于Hash算法本身的緣故,使用取模法進行緩存時,這種情況是無法避免的,為了解決這些問題而出現一致性哈希算法誕生。

????1.2Consistent hashing一致性算法原理

? ? 這和算法有一個環形hash空間的概念,通常hash算法都是將value映射在一個32位的key值當中,那么把數據首尾相接就會形成一個圓形,取值范圍為0 ~ 2^32-1,這個圓環就是環形hash空間。

hash環

我們來看如何把對象映射到環形hash空間:

? ? *只考慮4個對象Object1~Object4

? ? *首先通過hash函數計算出這四個對象的hash值key,這些對象的hash值肯定是會落在上述中的環形hash空間范圍上的,對象的hash對應的環形hash空間上的哪一個key值那么該對象就會映射到那個位置上,這樣對象就映射到hash空間上

對象映射過程

????然后就是把cache映射到環形hash空間,cache就是我們redis服務器,采用跟對象一樣的hash算法。

redis服務器跟對象映射到hash環

????可以看到,Cache和Obejct都映射到這個環形hash空間中了,那么接下來要考慮的就是如何將object映射到cache中。其實在這個環形hash空間進行一個順時針的計算即可,例如key1順時針遇到的第一個cache是cacheA,所以就將key1映射到cacheA中,key2順時針遇到的第一個cache是cacheC,那么就將key2映射到cacheC中,以此類推。

object節點順時針映射到redis節點

????如果某一個cache被移除之后,那么object會繼續順時針尋找下一個cache進行映射。例如,cacheB被移除了,映射在cacheB中的object4就會順時針往下找到cacheC,然后映射到cacheC上。

移除一個節點之后的變化

????所以當移除一個cacheB時所影響的object范圍就是cacheB與cacheA之間的那一段范圍,這個范圍是比較小的。如下圖所標出的范圍:

受影響的范圍,相比較原始的分布式算法,影響范圍小很多

????而當增加一個cache節點時也是同理,例如,在acheC和cacheB之間增加了一個cacheD節點,那么object2在順時針遇到的第一個cache就是cacheD,此時就會將obejct2映射到cacheD中。如下圖:

新增redis節點

????同樣的,增加cache節點所影響的范圍也就是cacheD和cacheB之間的那一段范圍。如下圖所標出的范圍:

影響范圍較小

1.3Hash傾斜性

? ? 上面一致性hash算法分析的都很美好,我們假設了所有的cache節點都在環形hash空間上均勻分布,但是很有可能會出現cache節點無法均勻分布在環形hash空間上。

cacheHahs之后分布到一側

????可以看到,A、B、C節點都擠在了一塊,按順時針來計算,就會有大量的數據(object)映射到A節點上,從上圖中來看就會有一大半的數據都映射到A節點上,那么A節點所承載的數據壓力會十分大,B、C節點則無法得到很好的利用,幾乎等同閑著沒事干。這就是Hash傾斜性所導致的現象,無法保證在環形hash空間上絕對的分布均勻。

? ? 1.4虛擬節點

? ??為了解決Hash傾斜性的問題,redis引入了虛擬節點的概念,虛擬節點相當于是實際節點的一個影子或者說分身,而且虛擬節點一般都比實際節點的數量要多(可能一下多好幾百倍,這個hash的環上都是密密麻麻的虛擬節點【默認的一個實際redis節點有160個虛擬節點,如果給redis實際節點配置了權重的話(默認權重是1),那虛擬節點的個數就是權重*160】)。引入虛擬節點后,object不再直接映射到實際的cache節點中,而是先映射到虛擬節點中。然后虛擬節點會再進行一個hash計算,最后才映射到實際的cache節點中。所以虛擬節點就是對我們的實際節點進行一個放大,如下圖:

淺色為虛擬節點,深色為實際節點

? ? 先把對象hash到虛擬節點上,在將虛擬節點重新hash到真是的redis節點上。如下圖所示:

虛擬節點hash的過程

? ? 1.5Consistent hashing命中率

? ? 命中率=(1 - n /(n+m))*100%(注釋: ? ? n = 現有的節點數量;m = 新增的節點數量)

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。