Redis詳解(九) 一致性hash演算法

2022-07-28 01:15:14 字數 2309 閱讀 7172

隨著業務的擴充套件,流量的劇增,單體專案逐漸劃分為分布式系統。對於經常使用的資料,我們可以使用redis作為快取機制,減少資料層的壓力。因此,重構後的系統架構如下圖所示:

優化最簡單的策略就是,把常用的資料儲存到redis中,為了實現高可用使用了3臺redis(沒有設定集群,集群至少要6臺)。每次redis請求會隨機傳送到其中一台,但是這種策略會引發如下兩個問題:

要解決上述的問題,我們需要稍稍改變一些key存入redis的規則:使用hash演算法

例如,有三颱redis,對於每次的訪問都可以通過計算hash來求得hash值。

如公式 h=hash(key)%3,我們把redis編號設定成0,1,2來儲存對應hash計算出來的值,h的值等於redis對應的編號。

但是hash演算法也會面臨容錯性和擴充套件性的問題。容錯性是指當系統中的某個服務出現問題時,不能影響其他系統。擴充套件性是指當加入新的伺服器後,整個系統能正確高效執行。

現假設有一台redis伺服器宕機了,那麼為了填補空缺,要將宕機的伺服器從編號列表中移除,後面的伺服器按順序前移一位並將其編號值減一,此時每個key就要按h = hash(key) % 2重新計算。

同樣,如果新增一台伺服器,規則也同樣需要重新計算,h = hash(key) % 4。因此,系統中如果有伺服器更變,會直接影響到hash值,大量的key會重定向到其他伺服器中,造成快取命中率降低,而這種情況在分布式系統中是十分糟糕的。

乙個設計良好的分布式雜湊方案應該具有良好的單調性,即服務節點的變更不會造成大量的雜湊重定位。一致性雜湊演算法由此而生~

一致雜湊 是一種特殊的雜湊演算法。在使用一致雜湊演算法後,雜湊表槽位數(大小)的改變平均只需要對 k/n 個關鍵字重新對映,其中k是關鍵字的數量, n是槽位數量。然而在傳統的雜湊表中,新增或刪除乙個槽位的幾乎需要對所有關鍵字進行重新對映。

簡單的說,一致性雜湊是將整個雜湊值空間組織成乙個虛擬的圓環,如假設雜湊函式h的值空間為0-2^32-1(雜湊值是32位無符號整形),整個雜湊空間環如下:

整個空間按順時針方向組織,0和2^32-1在零點中方向重合。

接下來,把伺服器按照ip或主機名作為關鍵字進行雜湊,這樣就能確定其在雜湊環的位置。

然後,我們就可以使用雜湊函式h計算值為key的資料在雜湊環的具體位置h,根據h確定在環中的具體位置,從此位置沿順時針滾動,遇到的第一台伺服器就是其應該定位到的伺服器。

例如我們有a、b、c、d四個資料物件,經過雜湊計算後,在環空間上的位置如下:

根據一致性雜湊演算法,資料a會被定為到server 1上,資料b被定為到server 2上,而c、d被定為到server 3上。

那麼使用一致性雜湊演算法的容錯性和擴充套件性如何呢?

假如redisservice2宕機了,那麼會怎樣呢?

那麼,資料b對應的節點儲存到redisservice3中。因此,其中一台宕機後,干擾的只有前面的資料(原資料被儲存到順時針的下乙個伺服器),而不會干擾到其他的資料。

下面考慮另一種情況,假如增加一台伺服器redis4,具體位置如下圖所示:

原本資料c是儲存到redis3中,但由於增加了redis4,資料c被儲存到redis4中。干擾的也只有redis3而已,其他資料不會受到影響。

因此,一致性雜湊演算法對於節點的增減都只需重定位換空間的一小部分即可,具有較好的容錯性和可擴充套件性

前面部分都是講述到redis節點較多和節點分布較為均衡的情況,如果節點較少就會出現節點分布不均衡造成資料傾斜問題。

例如,我們的的系統有兩台redis,分布的環位置如下圖所示:

這會產生一種情況,redis4的hash範圍比redis3的hash範圍大,導致資料大部分都儲存在redis4中,資料儲存不平衡。

為了解決這種資料儲存不平衡的問題,一致性雜湊演算法引入了虛擬節點機制,即對每個節點計算多個雜湊值,每個計算結果位置都放置在對應節點中,這些節點稱為虛擬節點

具體做法可以在伺服器ip或主機名的後面增加編號來實現,例如上面的情況,可以為每個服務節點增加三個虛擬節點,於是可以分為 redisservice1#1、 redisservice1#2、 redisservice1#3、 redisservice2#1、 redisservice2#2、 redisservice2#3,具體位置如下圖所示:

對於資料定位的hash演算法仍然不變,只是增加了虛擬節點到實際節點的對映。例如,資料c儲存到虛擬節點redis1#2,實際上資料儲存到redis1中。這樣,就能解決服務節點少時資料不平均的問題。在實際應用中,通常將虛擬節點數設定為32甚至更大,因此即使很少的服務節點也能做到相對均勻的資料分布

Redis 一致性Hash演算法

在redis 集群模式cluster中,redis採用的是分片sharding的方式,也就是將資料採用一定的分割槽策略,分發到相應的集群節點中。但是我們使用上述hash演算法進行快取時,會出現一些缺陷,主要體現在伺服器數量變動的時候,所有快取的位置都要發生改變!具體來講就是說第一當快取伺服器數量發生...

一致性hash演算法 面試必備 一致性hash演算法

最近公司在招人,我們準備的問題中有一道是關於一致性hash演算法的問題,只有一些面試者能夠回答上來,而且答的也不是很全面,有的面試者只是聽說過,有的連聽都沒聽過,下面我把一致性hash演算法整理一下分享給大家 一致性雜湊演算法在1997年由麻省理工學院的karger等人在解決分布式cache中提出的...

一致性hash演算法虛擬節點 一致性hash演算法

hash 演算法也叫做雜湊演算法,他可以讓任意長度的資料m對映成為長度固定的值h。hash演算法的第乙個作用就是資料的快速儲存與查詢。寫過程式的人都知道,基本上主流的程式語言裡面都有個資料結構叫做map dictionary或者 hash table 它是根據key來直接訪問結果的資料結構。key的...