Redis的資料分布演算法(雜湊槽)

2021-10-18 05:38:02 字數 4413 閱讀 6999

redis cluster 集群中涉及到了資料分布問題,因為 redis cluster 是多 master 的結構,每個 master 都是可以提供儲存服務的,這就會涉及到資料分布的問題,在新的 redis 版本中採用的是虛擬槽分割槽技術來解決資料分布的問題。

除了虛擬槽分割槽技術之外,還有幾種資料分布的演算法,比如雜湊演算法,一致性雜湊演算法,這篇文章我們就來一起聊一聊這幾種資料分布演算法。

因為是集群,所以我們需要乙個大前提,在這篇文章中假設 redis cluster 集群中有三颱 master,我們需要儲存的資料集為:[,,,,,],在這個大前提下,我們來聊一聊集群中的資料分布演算法。

雜湊演算法在分布式架構中應用廣泛,不僅僅是資料儲存,還有負載均衡等應用上有用的比較多,雜湊演算法的思想非常簡單,也許你知道 hashmap 的雜湊函式,雜湊演算法跟 hashmap 一樣,也是通過乙個雜湊函式得到某乙個數字,然後根據數字找到相應的伺服器。雜湊演算法的雜湊函式比較簡單,一般是根據某個key的值或者key 的雜湊值與當前可用的 master節點數取模,根據取模的值獲取具體的伺服器。雜湊演算法服務結構模型圖如下圖所示:

用我們前面假設的資料,利用雜湊演算法來實驗一把,加深我們對雜湊演算法在分布式中的應用的理。我們假設雜湊演算法中的雜湊函式為「id % master 節點數」,結果為 0 的資料存放到 server1 伺服器上,結果為 1 的資料存放到 server2 伺服器上,結果為 2 的資料存放到 server3 伺服器上。

所以經過雜湊演算法之後,id=3、id=6 的資料與 master 節點數取模為 0 (3%3=0,6%3=0),所以這兩個資料會存放到 server1 伺服器 ,以此類推,id=1、id=4 的資料將存放到 server2 伺服器中,id=2、id=5 的資料將存放到 server3 上,這時候伺服器儲存資料如下圖所示:

這就是雜湊演算法在分布式中的作用,比較簡單,可以看出只要你雜湊函式設計的好,資料在各個伺服器上是比較均勻分布的,但是雜湊演算法有乙個致命的缺點:擴充套件性特別的差,比如我們的集群中,伺服器server3 宕機了,這時候集群中可用的機器只有兩台了,這樣雜湊函式就變成了id % 2了,這就會導致乙個問題,所有的資料需要重新計算,找到新的儲存節點,每次有伺服器宕機或者新增機器時,都需要進行大量的資料遷移,這會使得系統的可用性、穩定性變差。

一致性雜湊演算法可以說是雜湊演算法的公升級版,解決了雜湊演算法擴充套件性差的問題,一致性雜湊演算法跟雜湊演算法不一樣,一致性雜湊演算法會將伺服器和資料都通過雜湊函式對映到乙個首尾相連的雜湊環上,儲存節點對映可以根據 ip 位址來進行雜湊取值,資料對映到雜湊環上後按照順時針的方向查詢儲存節點,即從資料對映在環上的位置開始,順時針方向找到的第乙個儲存節點,那麼他就儲存在這個節點上

我們使用一致性雜湊演算法來儲存我們的資料,我畫了一張圖來模擬一致性雜湊演算法可能出現的結果:

我們先來解讀一下這張圖,按照一致性雜湊演算法的規則,資料沿著順時針的方向查詢資料,那麼 id=4 的資料存放在 server1 伺服器,id=2 的資料存放在伺服器 server2 上,id=3、id=1、id=5、id=6 的資料都存放在伺服器 server3 上,如果你比較敏感的話,也許你就會發現一致性雜湊演算法的不足之處, 從圖中可以看出,我們六條資料分布不均勻,並不是每台伺服器儲存 2 條資料,而且差距好像還有點大,這裡我們就要來說一說一致性雜湊演算法的缺點:一致性雜湊演算法會會造成資料分布不均勻的問題或者叫做資料傾斜問題,就像我們圖中那樣,資料分布不均勻可能會造成某乙個節點的負載過大,從而宕機。造成資料分布不均勻有以下兩種情況:

前面我們提到過一致性雜湊演算法解決了雜湊演算法中擴充套件性差的問題,這個怎麼理解呢?我們來看看,在一致性雜湊演算法中當有儲存節點加入或者退出時,只會影響應該該節點的後繼節點,舉個例子說明一下,例如我們要在伺服器server3 和服務 server2 之間加入了乙個伺服器儲存節點 server4,只會對伺服器server3 造成影響,原本儲存到伺服器server3 上的資料有一部分會落入到伺服器 server4 上,對伺服器 server1 和 server2 並沒有任何影響,這樣就不會進行大量的資料遷移,擴充套件性就變強了。

因為一致性雜湊演算法的資料分布不均勻的問題,google 在 2017 年提出了帶有限負載的一致性雜湊演算法來解決這個問題,帶有限負載的一致性雜湊演算法思想比較簡單,給每個儲存節點設定了乙個儲存上限值來控制儲存節點新增或移除造成的資料不均勻,當資料按照一致性雜湊演算法找到相應的儲存節點時,要先判斷該儲存節點是否達到了儲存上限;如果已經達到了上限,則需要繼續尋找該儲存節點順時針方向之後的節點進行儲存。

我們利用帶有限負載的一致性雜湊演算法來改進上面的資料儲存,我們限定每台伺服器節點儲存的資料上限為 2 ,資料插入的順序就按照 id 大小的順序,同樣我也畫了一張模擬圖:

一起來分析一下這張圖,因為我們的新增順序是按照 id 大小的順序,所以前四個資料都沒有問題,這時候的伺服器都沒有超過最高負載數量,id=5 的資料落在了伺服器server2 和伺服器server3 之間,本應該是儲存在伺服器server3 上,但是由於此時的伺服器server3 上已經儲存了 id=1、id=3 的資料達到了最高限定,因此 id=5 的資料會沿著順時針的方向繼續往下尋找伺服器,下乙個伺服器就是server1,此時的伺服器server1 就儲存了 id=4 的資料並沒有達到上限,所以 id=5 的資料就會儲存在伺服器server1,id=6 的資料同樣的道理。這樣就利用帶有限負載的一致性雜湊演算法解決了一致性雜湊演算法中資料分布不均勻的問題。

帶有限負載的一致性雜湊演算法也有乙個問題,那就是每台伺服器的效能配置可能存在不一樣,如果規定數量過小的話,對於配置高的伺服器來說有點浪費,這是因為伺服器之間可能存在差異,叫做伺服器之間的異構性,為了解決伺服器之間的異構性問題,引入了一種叫做帶虛擬節點的一致性雜湊演算法,帶虛擬節點的一致性雜湊演算法核心思想是:根據每個節點的效能為每個節點劃分不同數量的虛擬節點,並將這些虛擬節點對映到雜湊環中,然後再按照一致性雜湊演算法進行資料對映和儲存

為了演示帶虛擬節點的一致性雜湊演算法,我們先做乙個假設伺服器server3是配置最差的,所以我們以伺服器server3 為基準,伺服器server2 是伺服器server3 的兩倍,伺服器server1 是伺服器server3 的三倍,有了這個前提之後,我們就可以來建立虛擬節點,我們假設伺服器server3 的虛擬節點為伺服器server3_1,伺服器server2 就有兩個虛擬節點伺服器server2_1、伺服器server2_2,伺服器server1 有三個虛擬節點 伺服器server1_1、伺服器server1_2、伺服器server1_3。我還是跟前面一樣畫了一張模擬圖:

落到虛擬節點上的資料都會存到對應的物理伺服器上,所以通過帶虛擬節點的一致性雜湊演算法後,資料儲存結果為:資料id=2、id=3、id=5 的資料都會儲存到伺服器server1 上,id=1 的資料將會儲存到伺服器server2 上,資料 id=4、id=6 都會存放到伺服器server3上。

虛擬節點可以讓配置好的伺服器儲存更多的資料,這樣就解決了系統異構性的問題,同時由於大量的虛擬節點的存在

在資料遷移時資料會落到不同的物理機上,這樣就減小了資料遷移時某台伺服器的分擔壓力,能夠保證系統的穩定性。

虛擬槽分割槽是 redis cluster 中預設的資料分布技術,虛擬槽分割槽巧妙地使用了雜湊空間,使用分散度良好的雜湊函式把所有資料對映到乙個固定範圍的整數集合中,這個整數定義為槽(slot),而且這個槽的個數一般遠遠的大於節點數。

在 redis cluster 中有16384(0~16383)個槽,會將這些槽平均分配到每個 master 上,在儲存資料時利用 crc16 演算法,具體的計算公式為:slot=crc16(key)/16384 來計算 key 屬於哪個槽。在我們的集群環境中,乙個 key 的儲存或者查詢過程,可能如下圖所示:

虛擬槽分割槽解耦了資料與節點的關係,通過引入槽,讓槽成為集群內資料管理和遷移的基本單位,簡化了節點擴容和收縮難度,你只需要關注資料在哪個槽,並不需要關心資料在哪個節點上。所以虛擬槽分割槽可以說比較好的相容了資料均勻分布和擴充套件性的問題。

Redis 雜湊槽概念

redis 集群中內建了 16384 個雜湊槽,當需要在 redis 集群中放置乙個 key value時,redis 先對 key 使用 crc16 演算法算出乙個結果,然後把結果對 16384 求餘數,這樣每個 key 都會對應乙個編號在 0 16383 之間的雜湊槽,redis 會根據節點數量...

redis集群之雜湊槽

clusterlink結構儲存了連線節點所需要的資訊,比如套接字描述符,輸入快取區和輸出緩衝區,主要是用於連線其他節點。每個節點都儲存著乙個clusterstate結構。這個結構記錄了在當前結點的視角下,集群的狀態,集群所包含的節點等資訊 redis 集群通過分片的方式儲存資料庫中的鍵值對 集群的整...

Redis集群中的雜湊槽

關係 cluster node slot key redis 集群中內建了 2 14 16384 個雜湊槽,當需要在 redis 集群中放置乙個 key value時,redis 先對 key 使用 crc16 演算法算出乙個結果,然後把結果對 16384 求餘數,這樣每個 key 都會對應乙個編號...