单个节点的缓存容量达到上限 Hash算法一致性
場(chǎng)景
?
單個(gè)節(jié)點(diǎn)的緩存容量達(dá)到上限,無(wú)法繼續(xù)單點(diǎn)增加內(nèi)存,如何解決?
單個(gè)節(jié)點(diǎn)支撐的QPS達(dá)到上限,如何解決??
初步方案
?
增加N個(gè)緩存節(jié)點(diǎn),為了保證緩存數(shù)據(jù)的均勻,一般情況會(huì)采用對(duì)key值hash,然后取模的方式,然后根據(jù)結(jié)果,確認(rèn)數(shù)據(jù)落到哪臺(tái)節(jié)點(diǎn)上:如下:
hash(key)%N?
很好,這個(gè)的確解決了上面的問(wèn)題,實(shí)現(xiàn)了初步的分布式緩存,數(shù)據(jù)均勻分散到了各個(gè)節(jié)點(diǎn)上,流量請(qǐng)求也均勻的分散到了各個(gè)節(jié)點(diǎn)。
但是如果出現(xiàn)以下情況,會(huì)帶來(lái)什么問(wèn)題?
1、某臺(tái)服務(wù)器突然宕機(jī)。緩存服務(wù)器從N變?yōu)镹-1臺(tái)。
2、緩存容量達(dá)到上限或者請(qǐng)求處理達(dá)到上限,需要增加緩存服務(wù)器,假定增加1臺(tái),則緩存服務(wù)器從N變?yōu)镹+1
上面的情況帶來(lái)的問(wèn)題:
增加或者刪除緩存服務(wù)器的時(shí)候,意味著大部分的緩存都會(huì)失效。這個(gè)是比較致命的一點(diǎn),緩存失效,如果業(yè)務(wù)為緩存不命中,查詢DB的話,會(huì)導(dǎo)致一瞬間DB的壓力陡增。可能會(huì)導(dǎo)致整個(gè)服務(wù)不可用。?
換種描述方式,我們需要解決怎么樣的問(wèn)題?或者需求是怎樣的?
?????增刪機(jī)器時(shí),希望大部分key依舊在原有的緩存服務(wù)器上保持不變。舉例來(lái)說(shuō):key1,key2,key3原先再Cache1機(jī)器上,現(xiàn)在增加一臺(tái)緩存服務(wù)器,希望key1,key2,key3依舊在Cache1機(jī)器上,而不是在Cache2機(jī)器上。?
?
改進(jìn)方案(一致性Hash)
?
一致性哈希算法的簡(jiǎn)單背景介紹 (此段內(nèi)容來(lái)自網(wǎng)絡(luò))
一致性哈希算法在1997年由麻省理工學(xué)院提出的一種分布式哈希(DHT)實(shí)現(xiàn)算法,設(shè)計(jì)目標(biāo)是為了解決因特網(wǎng)中的熱點(diǎn)(Hot spot)問(wèn)題,初衷和CARP十分類似。一致性哈希修正了CARP使用的簡(jiǎn)單哈希算法帶來(lái)的問(wèn)題,使得分布式哈希(DHT)可以在P2P環(huán)境中真正得到應(yīng)用。?
一致性hash算法提出了在動(dòng)態(tài)變化的Cache環(huán)境中,判定哈希算法好壞的四個(gè)定義:(來(lái)自百度百科)
平衡性(Balance):平衡性是指哈希的結(jié)果能夠盡可能分布到所有的緩沖中去,這樣可以使得所有的緩沖空間都得到利用。很多哈希算法都能夠滿足這一條件。
單調(diào)性(Monotonicity):單調(diào)性是指如果已經(jīng)有一些內(nèi)容通過(guò)哈希分派到了相應(yīng)的緩沖中,又有新的緩沖加入到系統(tǒng)中。哈希的結(jié)果應(yīng)能夠保證原有已分配的內(nèi)容可以被映射到原有的或者新的緩沖中去,而不會(huì)被映射到舊的緩沖集合中的其他緩沖區(qū)。?
分散性(Spread):在分布式環(huán)境中,終端有可能看不到所有的緩沖,而是只能看到其中的一部分。當(dāng)終端希望通過(guò)哈希過(guò)程將內(nèi)容映射到緩沖上時(shí),由于不同終端所見(jiàn)的緩沖范圍有可能不同,從而導(dǎo)致哈希的結(jié)果不一致,最終的結(jié)果是相同的內(nèi)容被不同的終端映射到不同的緩沖區(qū)中。這種情況顯然是應(yīng)該避免的,因?yàn)樗鼘?dǎo)致相同內(nèi)容被存儲(chǔ)到不同緩沖中去,降低了系統(tǒng)存儲(chǔ)的效率。分散性的定義就是上述情況發(fā)生的嚴(yán)重程度。好的哈希算法應(yīng)能夠盡量避免不一致的情況發(fā)生,也就是盡量降低分散性。?
負(fù)載(Load):負(fù)載問(wèn)題實(shí)際上是從另一個(gè)角度看待分散性問(wèn)題。既然不同的終端可能將相同的內(nèi)容映射到不同的緩沖區(qū)中,那么對(duì)于一個(gè)特定的緩沖區(qū)而言,也可能被不同的用戶映射為不同 的內(nèi)容。與分散性一樣,這種情況也是應(yīng)當(dāng)避免的,因此好的哈希算法應(yīng)能夠盡量降低緩沖的負(fù)荷。
所以通過(guò)上面的定義可以看到,簡(jiǎn)單的hash(key)%N的方式,違背了?單調(diào)性?的這個(gè)原則。原因如上面提到的,增刪機(jī)器的時(shí)候,原有的緩存大部分會(huì)失效,也就違背了單調(diào)性的原則。
?
介紹:
? ? 大部分文章都提到環(huán)形的hash空間,但是沒(méi)有講為什么是環(huán)形的。后面我會(huì)聊下我的想法。?
? ? 使用常見(jiàn)的hash算法可以把一個(gè)key值哈希到一個(gè)具有2^32個(gè)桶的空間中。也可以理解成,將key值哈希到 [0, 2^32) 的一個(gè)數(shù)字空間中。 我們假設(shè)這個(gè)是個(gè)首尾連接的環(huán)形空間。如下圖:
? 假設(shè)我們現(xiàn)在有key1,key2,key3,key4 4個(gè)key值,我們通過(guò)一定的hash算法,將其對(duì)應(yīng)到上面的環(huán)形hash空間中。
? ?k1=hash(key1);
? ?k2=hash(key2);
? ?k3=hash(key3);
? ?k4=hash(key4);
同樣的,假設(shè)我們有3臺(tái)cache服務(wù)器,把緩存服務(wù)器通過(guò)hash算法,加入到上述的環(huán)中。一般情況下是根據(jù)機(jī)器的IP地址或者唯一的計(jì)算機(jī)別名進(jìn)行哈希。
c1=hash(cache1);
c2=hash(cache2);
c3=hash(cache3);
接下來(lái)就是數(shù)據(jù)如何存儲(chǔ)到cache服務(wù)器上了,key值哈希之后的結(jié)果順時(shí)針找上述環(huán)形hash空間中,距離自己最近的機(jī)器節(jié)點(diǎn),然后將數(shù)據(jù)存儲(chǔ)到上面, 如上圖所示,k1 存儲(chǔ)到 c3 服務(wù)器上, k4,k3存儲(chǔ)到c1服務(wù)器上, k2存儲(chǔ)在c2服務(wù)器上。用圖表示如下:
增刪機(jī)器的情況
假設(shè)cache3服務(wù)器宕機(jī),這時(shí)候需要從集群中將其摘除。那么,之前存儲(chǔ)再c3上的k1,將會(huì)順時(shí)針尋找距離它最近的一個(gè)節(jié)點(diǎn),也就是c1節(jié)點(diǎn),這樣,k1就會(huì)存儲(chǔ)到c1上了,看一看下下面的圖,比較清晰。
摘除c3節(jié)點(diǎn)之后,只影響到了原先存儲(chǔ)再c3上的k1,而k3、k4、k2都沒(méi)有受到影響,也就意味著解決了最開(kāi)始的解決方案(hash(key)%N)中可能帶來(lái)的雪崩問(wèn)題。
增加節(jié)點(diǎn)原理和刪除時(shí)差不多~
新增C4節(jié)點(diǎn)之后,原先存儲(chǔ)到C1的k4,遷移到了C4,分擔(dān)了C1上的存儲(chǔ)壓力和流量壓力。
幾個(gè)問(wèn)題:
1、為什么需要想象成環(huán)形?
? ? 為了保證節(jié)點(diǎn)宕機(jī)摘除之后,原先存儲(chǔ)在當(dāng)前節(jié)點(diǎn)的key能找到可存儲(chǔ)的位置。舉個(gè)極端的例子,在不是環(huán)狀hash空間下,剛好緩存的服務(wù)器處于0這個(gè)位置,那么0之后是沒(méi)有任何節(jié)點(diǎn)信息的,那么當(dāng)緩存服務(wù)器摘除的時(shí)候,以前存儲(chǔ)在這臺(tái)機(jī)器上的key便找不到順時(shí)針距離它最近的一個(gè)節(jié)點(diǎn)了。但如果是環(huán)形空間,0之后的最近的一個(gè)節(jié)點(diǎn)信息有可能是2^32-1這個(gè)位置,他可以找到0之后的節(jié)點(diǎn)。如下圖描述可能清晰一點(diǎn)。
?
2、為什么是2^32個(gè)桶空間?
? 沒(méi)有搞清楚,個(gè)人理解是為了保證足夠的靈活性,減少hash帶來(lái)的key值沖突。也方便后續(xù)增刪節(jié)點(diǎn)。?
繼續(xù)改進(jìn)
?
上面的簡(jiǎn)單的一致性hash的方案在某些情況下但依舊存在問(wèn)題:一個(gè)節(jié)點(diǎn)宕機(jī)之后,數(shù)據(jù)需要落到距離他最近的節(jié)點(diǎn)上,會(huì)導(dǎo)致下個(gè)節(jié)點(diǎn)的壓力突然增大,可能導(dǎo)致雪崩,整個(gè)服務(wù)掛掉。
如下圖所示,
當(dāng)節(jié)點(diǎn)C3摘除之后,之前再C3上的k1就要遷移到C1上,這時(shí)候帶來(lái)了兩部分的壓力:
? ? ?1)、之前請(qǐng)求到C3上的流量轉(zhuǎn)嫁到了C1上,會(huì)導(dǎo)致C1的流量增加,如果之前C3上存在熱點(diǎn)數(shù)據(jù),則可能導(dǎo)致C1扛不住壓力掛掉。
? ? ?2)、之前存儲(chǔ)到C3上的key值轉(zhuǎn)義到了C1,會(huì)導(dǎo)致C1的內(nèi)容占用量增加,可能存在瓶頸。
當(dāng)上面兩個(gè)壓力發(fā)生的時(shí)候,可能導(dǎo)致C1節(jié)點(diǎn)也宕機(jī)了。那么壓力便會(huì)傳遞到C2上,又出現(xiàn)了類似滾雪球的情況,服務(wù)壓力出現(xiàn)了雪崩,導(dǎo)致整個(gè)服務(wù)不可用。
如果解決上面的問(wèn)題?
虛擬節(jié)點(diǎn)。歪果人的腦子真好使,想出這么一個(gè)牛逼的方式,虛擬節(jié)點(diǎn)。
如上描述,一個(gè)節(jié)點(diǎn)宕機(jī)之后可能會(huì)引起下個(gè)節(jié)點(diǎn)的存儲(chǔ)及流量壓力變大,這一點(diǎn)違背了最開(kāi)始提到的四個(gè)原則中的 平衡性, 節(jié)點(diǎn)宕機(jī)之后,流量及內(nèi)存的分配方式打破了原有的平衡。
虛擬節(jié)點(diǎn),從名字可以看出來(lái),這個(gè)節(jié)點(diǎn)是個(gè)虛擬的,每個(gè)實(shí)際節(jié)點(diǎn)對(duì)應(yīng)多個(gè)虛擬節(jié)點(diǎn)。比較專業(yè)的說(shuō)法如下:
“虛擬節(jié)點(diǎn)”( virtual node )是實(shí)際節(jié)點(diǎn)(機(jī)器)在 hash 空間的復(fù)制品( replica ),一實(shí)際個(gè)節(jié)點(diǎn)(機(jī)器)對(duì)應(yīng)了若干個(gè)“虛擬節(jié)點(diǎn)”,這個(gè)對(duì)應(yīng)個(gè)數(shù)也成為“復(fù)制個(gè)數(shù)”,“虛擬節(jié)點(diǎn)”在 hash 空間中以hash值排列。
依舊用圖片來(lái)解釋,假設(shè)存在以下的真實(shí)節(jié)點(diǎn)和虛擬節(jié)點(diǎn)的對(duì)應(yīng)關(guān)系。
Visual100—> Real1
Visual101—> Real1
Visual200—> Real2
Visual201—> Real2
Visual300—> Real3
Visual301—> Real3
同樣的,hash之后的結(jié)果如下:
hash(Visual100)—> V100 ?—> Real1
hash(Visual101)—> V101? —> Real1
hash(Visual200)—> V200 ?—> Real2
hash(Visual201)—> V201? —> Real2
hash(Visual300)—> V300 ?—> Real3
hash(Visual301)—> V301 ?—> Real3
key值的hash結(jié)果如上,這里暫時(shí)不寫了。
如圖解釋:
和之前介紹的不添加虛擬節(jié)點(diǎn)的類似,主要聊下如果宕機(jī)之后的情況。?
假設(shè)Real1機(jī)器宕機(jī),則會(huì)發(fā)生一下情況。
1、原先存儲(chǔ)在虛擬節(jié)點(diǎn)V100上的k1數(shù)據(jù)將遷移到V301上,也就意味著遷移到了Real3機(jī)器上。?
2、原先存儲(chǔ)再虛擬節(jié)點(diǎn)V101上的k4數(shù)據(jù)將遷移到V200上,也就意味著遷移到了Real2機(jī)器上。
結(jié)果如下圖:
這個(gè)就解決之前的問(wèn)題了,某個(gè)節(jié)點(diǎn)宕機(jī)之后,存儲(chǔ)及流量壓力并沒(méi)有全部轉(zhuǎn)移到某臺(tái)機(jī)器上,而是分散到了多臺(tái)節(jié)點(diǎn)上。解決了節(jié)點(diǎn)宕機(jī)可能存在的雪崩問(wèn)題。
當(dāng)物理節(jié)點(diǎn)多的時(shí)候,虛擬節(jié)點(diǎn)多,這個(gè)的雪崩可能就越小。
PS:只有2個(gè)節(jié)點(diǎn)的時(shí)候,加入虛擬節(jié)點(diǎn)沒(méi)有用。你懂的。?
總結(jié)
以上是生活随笔為你收集整理的单个节点的缓存容量达到上限 Hash算法一致性的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 一致性哈希算法 应用
- 下一篇: 编程算法 - 将排序数组按绝对值大小排序