用hash做緩存,假如有三臺(tái)服務(wù)器,1,2,3,有三萬(wàn)張圖片,我想將圖片平均緩存到我三臺(tái)服務(wù)器上,一個(gè)服務(wù)器大概一萬(wàn)張,怎么去實(shí)現(xiàn)這個(gè)辦法呢,可以用hash來(lái)取余數(shù)進(jìn)行操作,加入我們是以圖片的名字作為key進(jìn)行hash計(jì)算,hash (圖片名稱)%N 其中N為我們服務(wù)器的個(gè)數(shù),我們將hash(圖片名稱)這一部分進(jìn)行計(jì)算后得到的是一個(gè)正數(shù),然后除以服務(wù)器的數(shù)目進(jìn)行取余數(shù),結(jié)果將會(huì)是0,1,2三個(gè)數(shù),對(duì)應(yīng)我們的服務(wù)器的編號(hào),當(dāng)我們作為客戶端去請(qǐng)求圖片的時(shí)候,圖片已經(jīng)進(jìn)行過(guò)hash運(yùn)算了,直接找到對(duì)應(yīng)服務(wù)器的編號(hào)進(jìn)行圖片的訪問(wèn),這樣解決了我需要遍歷所有的服務(wù)器進(jìn)行查找。
那如果我緩存的服務(wù)器的數(shù)量減少或者增加,如果還是按照原來(lái)的算法走,必定會(huì)造成緩存數(shù)據(jù)的丟失,會(huì)去向后端的服務(wù)器去請(qǐng)求,如果有一臺(tái)緩存服務(wù)器發(fā)生了故障,那我原來(lái)緩存的位置必定會(huì)發(fā)生改變,原來(lái)本該運(yùn)算后要進(jìn)行緩存到某一臺(tái)服務(wù)器的圖片,現(xiàn)在找不到對(duì)應(yīng)緩存服務(wù)器,肯定會(huì)發(fā)生緩存的雪崩
所以出現(xiàn)了一致性hash算法相當(dāng)于將服務(wù)器和圖片分別hash到我的hash環(huán)上進(jìn)行就近緩存,hash環(huán)就是對(duì)2^32次方進(jìn)行取模,從0開(kāi)始一直到2^32,均勻分布在一個(gè)圓環(huán)(一個(gè)比方),0的順時(shí)針?lè)较虻牡谝晃粸?,逆時(shí)針?lè)较虻谝晃粸?^32,大概如下圖
具體就是比方我有三個(gè)服務(wù)器A,B ,C對(duì)其進(jìn)行 hash (服務(wù)器Aip)%2^32 得出來(lái)的一定是一個(gè)整數(shù),而且一定是在0–2^32之間,那么這個(gè)數(shù)就會(huì)分布在hash環(huán)上對(duì)應(yīng)的位置,相同的B,C都一樣,假設(shè)我們hash過(guò)后ABC的位置如下圖
然后我們將需要緩存圖片的key進(jìn)行hash,它的hash值也會(huì)分布在我的hash環(huán)上,
如上圖,我hash到了A和C之間,圖片的存儲(chǔ)規(guī)則是順時(shí)針?lè)较虻拇鎯?chǔ),所以應(yīng)該存儲(chǔ)到A,如果有四張的話如下圖
那如果我們的hash算法將服務(wù)器和hash的圖片存放位置比較相近,類似于;
所有的緩存都集中存儲(chǔ)到了A一臺(tái),只有5到了B,那么這樣A的壓力就不言而喻,沒(méi)有均勻可言了,辛虧hash環(huán)可以添加緩存服務(wù)器的虛擬節(jié)點(diǎn),類似于虛擬機(jī),一臺(tái)實(shí)機(jī)可以虛擬多臺(tái),類似于這樣:
這樣的話就會(huì)盡可能的把緩存都均衡放在各個(gè)服務(wù)器
一致性hash算法的優(yōu)勢(shì)在哪:一個(gè)是當(dāng)我有一臺(tái)緩存節(jié)點(diǎn)掛了之后,緩存的存儲(chǔ)不會(huì)受太大的影響,
我們將b節(jié)點(diǎn)拿走,本來(lái)要在B節(jié)點(diǎn)存儲(chǔ)的3,因?yàn)檎也坏紹服務(wù)器,而遵循規(guī)則緩存到C,而4的緩存節(jié)點(diǎn)不會(huì)發(fā)生改變,這就是一致hash的優(yōu)點(diǎn),如果發(fā)生服務(wù)器的增加或者減少只有部分的緩存會(huì)失效,不造成全盤皆輸?shù)目赡?/p>
一致hash到此結(jié)束。