????本文主要會圍繞,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空間:
? ? *只考慮4個對象Object1~Object4
? ? *首先通過hash函數計算出這四個對象的hash值key,這些對象的hash值肯定是會落在上述中的環形hash空間范圍上的,對象的hash對應的環形hash空間上的哪一個key值那么該對象就會映射到那個位置上,這樣對象就映射到hash空間上
????然后就是把cache映射到環形hash空間,cache就是我們redis服務器,采用跟對象一樣的hash算法。
????可以看到,Cache和Obejct都映射到這個環形hash空間中了,那么接下來要考慮的就是如何將object映射到cache中。其實在這個環形hash空間進行一個順時針的計算即可,例如key1順時針遇到的第一個cache是cacheA,所以就將key1映射到cacheA中,key2順時針遇到的第一個cache是cacheC,那么就將key2映射到cacheC中,以此類推。
????如果某一個cache被移除之后,那么object會繼續順時針尋找下一個cache進行映射。例如,cacheB被移除了,映射在cacheB中的object4就會順時針往下找到cacheC,然后映射到cacheC上。
????所以當移除一個cacheB時所影響的object范圍就是cacheB與cacheA之間的那一段范圍,這個范圍是比較小的。如下圖所標出的范圍:
????而當增加一個cache節點時也是同理,例如,在acheC和cacheB之間增加了一個cacheD節點,那么object2在順時針遇到的第一個cache就是cacheD,此時就會將obejct2映射到cacheD中。如下圖:
????同樣的,增加cache節點所影響的范圍也就是cacheD和cacheB之間的那一段范圍。如下圖所標出的范圍:
1.3Hash傾斜性
? ? 上面一致性hash算法分析的都很美好,我們假設了所有的cache節點都在環形hash空間上均勻分布,但是很有可能會出現cache節點無法均勻分布在環形hash空間上。
????可以看到,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節點上。如下圖所示:
? ? 1.5Consistent hashing命中率
? ? 命中率=(1 - n /(n+m))*100%(注釋: ? ? n = 現有的節點數量;m = 新增的節點數量)