Redis:一致性Hash算法
1. 前言
在Redis 集群模式Cluster中,Redis采用的是分片Sharding的方式,也就是將數(shù)據(jù)采用一定的分區(qū)策略,分發(fā)到相應(yīng)的集群節(jié)點(diǎn)中。但是我們使用上述HASH算法進(jìn)行緩存時(shí),會(huì)出現(xiàn)一些缺陷,主要體現(xiàn)在服務(wù)器數(shù)量變動(dòng)的時(shí)候,所有緩存的位置都要發(fā)生改變!具體來講就是說第一當(dāng)緩存服務(wù)器數(shù)量發(fā)生變化時(shí),會(huì)引起緩存的雪崩,可能會(huì)引起整體系統(tǒng)壓力過大而崩潰(大量緩存同一時(shí)間失效)。第二當(dāng)緩存服務(wù)器數(shù)量發(fā)生變化時(shí),幾乎所有緩存的位置都會(huì)發(fā)生改變。
2. 一致性哈希的基本概念
一致性Hash算法也是使用取模的方法,只是,剛才描述的取模法是對服務(wù)器的數(shù)量進(jìn)行取模,而一致性Hash算法是對232取模,什么意思呢?簡單來說,一致性Hash算法將整個(gè)哈希值空間組織成一個(gè)虛擬的圓環(huán),如假設(shè)某哈希函數(shù)H的值空間為0-232-1(即哈希值是一個(gè)32位無符號(hào)整形),整個(gè)哈希環(huán)如下:
整個(gè)空間按順時(shí)針方向組織,圓環(huán)的正上方的點(diǎn)代表0,0點(diǎn)右側(cè)的第一個(gè)點(diǎn)代表1,以此類推,2、3、4、5、6……直到232-1,也就是說0點(diǎn)左側(cè)的第一個(gè)點(diǎn)代表232-1, 0和232-1在零點(diǎn)中方向重合,我們把這個(gè)由232個(gè)點(diǎn)組成的圓環(huán)稱為Hash環(huán)。
那么,一致性哈希算法與上圖中的圓環(huán)有什么關(guān)系呢?我們繼續(xù)聊,仍然以之前描述的場景為例,假設(shè)我們有4臺(tái)緩存服務(wù)器,服務(wù)器A、服務(wù)器B、服務(wù)器C,服務(wù)器D,那么,在生產(chǎn)環(huán)境中,這4臺(tái)服務(wù)器肯定有自己的IP地址或主機(jī)名,我們使用它們各自的IP地址或主機(jī)名作為關(guān)鍵字進(jìn)行哈希計(jì)算,使用哈希后的結(jié)果對2^32取模,可以使用如下公式示意:
hash(服務(wù)器A的IP地址) % 2^32通過上述公式算出的結(jié)果一定是一個(gè)0到232-1之間的一個(gè)整數(shù),我們就用算出的這個(gè)整數(shù),代表服務(wù)器A,既然這個(gè)整數(shù)肯定處于0到232-1之間,那么,上圖中的hash環(huán)上必定有一個(gè)點(diǎn)與這個(gè)整數(shù)對應(yīng),而我們剛才已經(jīng)說明,使用這個(gè)整數(shù)代表服務(wù)器A,那么,服務(wù)器A就可以映射到這個(gè)環(huán)上。
以此類推,下一步將各個(gè)服務(wù)器使用類似的Hash算式進(jìn)行一個(gè)哈希,這樣每臺(tái)機(jī)器就能確定其在哈希環(huán)上的位置,這里假設(shè)將上文中四臺(tái)服務(wù)器使用IP地址哈希后在環(huán)空間的位置如下:
接下來使用如下算法定位數(shù)據(jù)訪問到相應(yīng)服務(wù)器: 將數(shù)據(jù)key使用相同的函數(shù)Hash計(jì)算出哈希值,并確定此數(shù)據(jù)在環(huán)上的位置,從此位置沿環(huán)順時(shí)針“行走”,第一臺(tái)遇到的服務(wù)器就是其應(yīng)該定位到的服務(wù)器!
3. 一致性Hash算法的容錯(cuò)性和可擴(kuò)展性
現(xiàn)假設(shè)Node C不幸宕機(jī),可以看到此時(shí)對象A、B、D不會(huì)受到影響,只有C對象被重定位到Node D。一般的,在一致性Hash算法中,如果一臺(tái)服務(wù)器不可用,則受影響的數(shù)據(jù)僅僅是此服務(wù)器到其環(huán)空間中前一臺(tái)服務(wù)器(即沿著逆時(shí)針方向行走遇到的第一臺(tái)服務(wù)器)之間數(shù)據(jù),其它不會(huì)受到影響,如下所示:
下面考慮另外一種情況,如果在系統(tǒng)中增加一臺(tái)服務(wù)器Node X,如下圖所示:
此時(shí)對象Object A、B、D不受影響,只有對象C需要重定位到新的Node X !一般的,在一致性Hash算法中,如果增加一臺(tái)服務(wù)器,則受影響的數(shù)據(jù)僅僅是新服務(wù)器到其環(huán)空間中前一臺(tái)服務(wù)器(即沿著逆時(shí)針方向行走遇到的第一臺(tái)服務(wù)器)之間數(shù)據(jù),其它數(shù)據(jù)也不會(huì)受到影響。
綜上所述,一致性Hash算法對于節(jié)點(diǎn)的增減都只需重定位環(huán)空間中的一小部分?jǐn)?shù)據(jù),具有較好的容錯(cuò)性和可擴(kuò)展性。
4. Hash環(huán)的數(shù)據(jù)傾斜問題
一致性Hash算法在服務(wù)節(jié)點(diǎn)太少時(shí),容易因?yàn)楣?jié)點(diǎn)分部不均勻而造成數(shù)據(jù)傾斜(被緩存的對象大部分集中緩存在某一臺(tái)服務(wù)器上)問題,例如系統(tǒng)中只有兩臺(tái)服務(wù)器,其環(huán)分布如下:
此時(shí)必然造成大量數(shù)據(jù)集中到Node A上,而只有極少量會(huì)定位到Node B上,從而出現(xiàn)hash環(huán)偏斜的情況,當(dāng)hash環(huán)偏斜以后,緩存往往會(huì)極度不均衡的分布在各服務(wù)器上,如果想要均衡的將緩存分布到2臺(tái)服務(wù)器上,最好能讓這2臺(tái)服務(wù)器盡量多的、均勻的出現(xiàn)在hash環(huán)上,但是,真實(shí)的服務(wù)器資源只有2臺(tái),我們怎樣憑空的讓它們多起來呢,沒錯(cuò),就是憑空的讓服務(wù)器節(jié)點(diǎn)多起來,既然沒有多余的真正的物理服務(wù)器節(jié)點(diǎn),我們就只能將現(xiàn)有的物理節(jié)點(diǎn)通過虛擬的方法復(fù)制出來。
這些由實(shí)際節(jié)點(diǎn)虛擬復(fù)制而來的節(jié)點(diǎn)被稱為"虛擬節(jié)點(diǎn)",即對每一個(gè)服務(wù)節(jié)點(diǎn)計(jì)算多個(gè)哈希,每個(gè)計(jì)算結(jié)果位置都放置一個(gè)此服務(wù)節(jié)點(diǎn),稱為虛擬節(jié)點(diǎn)。具體做法可以在服務(wù)器IP或主機(jī)名的后面增加編號(hào)來實(shí)現(xiàn)。
例如上面的情況,可以為每臺(tái)服務(wù)器計(jì)算三個(gè)虛擬節(jié)點(diǎn),于是可以分別計(jì)算 “Node A#1”、“Node A#2”、“Node A#3”、“Node B#1”、“Node B#2”、“Node B#3”的哈希值,于是形成六個(gè)虛擬節(jié)點(diǎn):
同時(shí)數(shù)據(jù)定位算法不變,只是多了一步虛擬節(jié)點(diǎn)到實(shí)際節(jié)點(diǎn)的映射,例如定位到“Node A#1”、“Node A#2”、“Node A#3”三個(gè)虛擬節(jié)點(diǎn)的數(shù)據(jù)均定位到Node A上。這樣就解決了服務(wù)節(jié)點(diǎn)少時(shí)數(shù)據(jù)傾斜的問題。在實(shí)際應(yīng)用中,通常將虛擬節(jié)點(diǎn)數(shù)設(shè)置為32甚至更大,因此即使很少的服務(wù)節(jié)點(diǎn)也能做到相對均勻的數(shù)據(jù)分布。
總結(jié)
以上是生活随笔為你收集整理的Redis:一致性Hash算法的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Redis:Redis集群模式(Clus
- 下一篇: Spark详解(十四):Spark SQ