Redis入門:數據分片算法

Redis入門:數據分片算法

1 Hash取餘

hash取餘對數據key-value的key值做hash取餘計算,得到結果只要key值不變(字符串相等)取餘結果在[0,1,2,3,…,n-1],n=分片個數(節點個數)。 計算公式如下:

(key.hashCode()&Integer.MAX_VALUE)%N
# 其中N爲分片(節點)個數
  • key.hashCode():對key做hash散列計算,只要key值不變,得到一個不變可正可負的整數。只要散列計算,能夠做到key不變,整數結果不變,不一定非得使用hashCode最終任意一個key值都會對應[-21億,21億]區間的一個整數。
  • key.hashCode()&Integer.MAX_VALUE:31位二進制保真運算,目的是將前面的整數保真後31位二進制,保證他是一個正整數。&位的與運算。目的是取得一個正整數。

結論1:當key值不變時,可以得到一個不變的正整數。

(key.hashCode()&Integer.MAX_VALUE)%N
N=5,取餘結果 [0,1,2,3,4]
N=4,取餘結果 [0,1,2,3]
N=3,取餘結果 [0,1,2]
對N取餘 結果[0,1,2,3,4,5…,N-1]

結論2:當key值不變時,可以通過hash取餘得到[0,1,2,…,N-1]一個不變的取餘結果。

hash取餘就可以應用在redis分佈式數據分片計算邏輯中。

當有key-value出現時,先對key做hash取餘n是節點個數(現在是3);所有節點jedis排序(list) 0 1 2 … n-1 使用到取餘結果對應到一個固定的jedis對象,最終連接固定的redis節點。

在一個頻繁發生擴容縮容的分佈式結構中,hash取餘不適用,但是N不發生變化的結構中總是使用hash取餘。

1.1 缺點

作爲散列算法,考慮分佈式緩存中的數據分片過程的哈希取餘的缺點。

1.1.1 散列算法都會出現數據傾斜

數據傾斜:

例如:3個redis節點,在散列計算後的存儲數據有可能是以下情況:

  • Node1:4000條數據。
  • Node2:3000條數據。
  • Node3:1500條數據。

此情況已經產生了2500條數據的最大偏移,按此比例計算,當數據存儲量上億條時,這種數據傾斜會造成集羣中節點間巨大的負載差距。

解決數據傾斜的方法:

  • 可以在key值上做文章。因爲key值是自定義的,所以可以使用uuid或者md5加密,來保證key的散列平均分佈。在key取值的時候就進行散列分佈。

1.1.2 大量數據遷移

哈希取餘的散列計算,在增加或者減少節點的時候,會導致數據遷移量過大。

2 Hash一致性

由上述原因,jedis的數據分片沒有使用hash取餘計算而是引入的hash一致性。

1997年麻省理工學院的學生開發了哈希一致性的計算方法。引入了一個0-43億的整數哈希環(0-2^32),把節點的ip和端口和其他信息作爲字符串的對象進行散列計算。

例如:"192.168.40.120:6379^$&$%"--散列計算--[0-2^32]的整數。

jedis對將要存儲的key做同樣的散列計算。

例如:"ITEM_CAT_0"--散列計算--[0-2^32]的整數。

利用這個hash環上的對應內容的散列結果,對key做順時針尋找最近節點映射整數的判斷,以這樣一種計算,將所有的key值進行數據分片的計算。

如下圖所示:

  • key1順時針最近節點——node1
  • key2,key3順時針最近節點——node3
  • key4順時針最近節點——node2

2.1特點

2.1.1減少增刪節點的數據遷移量

當增加節點node4時,如下圖:

對於當前存在的數據,只需要根據順時針最近節點的計算原理,遷移key4,其他的key都不用動。按此來說,只要遷移綠色線條上的數據即可。

當節點刪除時(node3),如下圖:

對於當前存在的數據,只需要遷移key2和key3到node2即可。如果數據較多,只需遷移node3的數據到node2即可,也就是藍色線條上的所有數據。

2.1.2解決數據平衡的問題

單獨的使用節點ip+端口+其他信息的散列映射,有可能導致數據的傾斜量過大。爲了解決數據平衡的問題,hash一致性引入虛擬節點的概念。

針對虛擬節點的官方說明,每個物理節點默認會產生1000個虛擬節點,散列分佈在hash環上,就相當於每個物理節點分割成了1001個節點,這樣多節點的散列分佈就能保證數據的平衡存儲。如下圖:

在沒有虛擬節點的情況下,node2需要存儲key2、key3、key4、key5,node1存儲key1,數據就產生了較大的傾斜。

當引入了虛擬節點的映射(ip+端口+#1),虛擬節點大致算法如下:

  • node1-node1-01:"192.168.40.139:6379#01"
  • node1-node1-02:"192.168.40.139:6379#02"

此時key值存放結果變成node1存儲key1、key2、key4,node2存儲key3、key5。數據存儲就相對平均了。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章