Redis分散式演算法原理
傳統分散式演算法
如果有3個redis服務節點,分別是redis0,redis1,redis2 。現在一個資源,對他進行hash之後除3取餘,餘數分別是0,1,2 ,根據餘數將該資源儲存到對應的redis節點上。

當有4個redis服務節點,20個資源時,資源的分佈情況如下:

此時如果再加入一個redis節點,仍然將這20個資源分配,則新的資源分佈情況如下:

此時發現,只有資源1,2,3,20仍然存在redis數量變化前對應的redis節點上。因此此時的命中率為20%,即redis節點數從4個變成5個時,原有資源仍存放在對應redis節點上的概率為20%,剩下80%需要重新分配,影響較大。因此刪除或增加一個redis節點,用傳統的演算法會使大量的快取丟失,對後臺伺服器造成大量衝擊。資料量達到百萬千萬級時,如果業務程式碼是穿透型的,會有大量的資料穿過cache直擊DB,把資料庫搞垮。
Consistent hashing 一致性演算法原理
而一致性hash演算法會將value對映在一個32位的keys值中,現在把這個數軸捲起來,形成了一個環形hash空間上。過程則是將物件對映到hash空間中。

現在,考慮4個物件object1~object4,通過hash函式計算出這4個物件的hash值key,落在環形hash空間上。如圖:

接下來將cache也通過相同的hash演算法,對映到同一個hash數值空間中。

現在是如何將物件存到對應的cache上的問題,在這個環形空間中,每個object都沿順時針儲存到裡他最近的cache上,又因為每個物件和cache都是通過相同的hash演算法得到,他們在這個環形空間的位置會是固定的,因此則會形成如下儲存關係:
cacheA :object1
cacheB:object4
cacheC:object3,object2
如果此時架構變動,移除一個cache節點B,此時產生變化的object4將會儲存到cacheC上。因此,產生影響的範圍是cacheB與cacheA之間的範圍,影響相對小很多。
而此時如果不是移除節點,而是新增一個節點cacheD,object2不在存放在cacheC上,而是會存放到cacheD上,此時影響的範圍也知會在cacheB到cacheD之間。所以無論增加或刪除一個節點,影響的範圍都是很小的。

Hash傾斜性
但是hash演算法又有傾斜性,上圖中ABC3個cache節點分佈的都比較均勻,而實際的情況會是如下圖所示,ABC他們可能會捱得非常緊。從圖中來看將會有大量的資料落在A上,不具有隨機性,3個cache節點的負載效能都不均勻。

虛擬節點
因此需要增加虛擬節點。每個cache節點都會生成一個虛擬節點,並重新hash,重新散佈到環形hash空間上,如下圖,相對均勻了一些。

但即便是增加虛擬節點,還是會出現hash傾斜性的問題。的確,因此實際編碼過程中配置一定的虛擬節點與真實節點的比例,隨著資料越來越多,虛擬節點越來越低,使影響降到最低。
Consistent hashing命中率
命中率計算公式:
(1-n/(n+m))*100%
伺服器臺數是n,而新增的伺服器臺數是m。當變動的伺服器臺數m越大,命中率越大,所以在變動時影響越來越小。當分散式叢集越來越大時,一致性hash演算法的優勢就越明顯。
redis分散式運用
redis分散式連線池取的ShardedJedis物件,而這個物件最終繼承自Sharded,原始碼中也可以看出,初始化分塊時,會有160乘以權重的虛擬節點。一般場景中會設定100-500個虛擬節點。

分散式與叢集的區別
叢集是一種物理配置;
分散式是一種工作方式。
分散式是以縮短單個任務的執行時間來提升效率的;
叢集是通過提高單位時間內執行的任務數來提升效率的。
偶然看到下圖,覺得十分形象。
