Redis 集羣

虛擬槽分區

redis集羣使用的是基於hash的一種分區算法,稱之爲虛擬槽分區

虛擬槽算法巧妙地使用了哈希空間,使用分散度良好的哈希函數將數據映射到一個固定範圍內的整數集合,整數集合中的每個整數稱爲一個槽(slot) ,這個整數範圍遠遠大於節點數。槽是集羣內數據管理;和遷移的基本單位。採用大範圍槽的主要目的是爲了方便數據拆分集羣擴展。每個節點會負責一定數量的槽,如圖所示:

當前集羣有5個節點,每個節點平均大約負責3276個槽。由於採用高質量的哈希算法,每個槽所映射的數據通常比較均勻,將數據平均劃分到 5個節點進行數據分區。

這種結構很容易添加或者刪除 節點。如果增加一個節點 6,就需要從節點 1 ~ 5 獲得部分槽分配到節點 6 上。如果想移除節點 1,需要將節點 1 中的槽移到節點 2 ~ 5 上,然後將沒有任何槽的節點 1 從集羣中移除即可。

由於從一個節點將哈希槽移動到另一個節點並不會停止服務,所以無論添加刪除或者改變某個節點的哈希槽的數量都不會造成集羣不可用的狀態。

Redis的數據分區

Redis Cluster 採用CRC16哈希函數+取餘方法將數據分爲16384個數據槽中:

slot = CRC16(key)& 16383

集羣中每個節點負責一部分槽以及槽所映射的鍵值數據。

優點
  • 解耦數據和節點之間的關係,簡化了節點擴容和收縮難度。
  • 節點自身維護槽的映射關係,不需要客戶端或者代理服務維護槽分區元數據。
  • 支持節點、槽、鍵之間的映射查詢,用於數據路由、在線伸縮等場景。
問題
  • key的批量操作命令會失效
  • key的事務操作失效
  • 不支持多數據庫空間,只使用db0
  • 複製結構只支持一層

數據定位

在redis集羣啓動時,需要指定每個節點各自管理的槽。當節點啓動時,需要發握手命令使得節點相互連通,節點會互發管理信息。此時集羣的狀態爲down。當節點確定所有的數據槽都有相應的節點管理時,集羣狀態修改爲up,可以進行數據管理。

客戶端只需要連接到一個節點,即可進行數據操作。該節點接收到數據命令時,會根據key計算數據槽:若歸自己管理,則直接執行命令並返回結果;若不歸自己管理,則發送MOVEN命令給客戶端,告訴客戶端相應的服務器位置,客戶端重定向到正確的服務器上執行命令。

數據遷移

無論是新增還是減少一個節點,本質都是將該節點的數據遷移到另外一個或多個節點。

節點數據的遷移是以slot爲單位的,具體流程:

  1. 在目標節點上聲明將從源節點上遷入Slot CLUSTER SETSLOT <slot> IMPORTING <source_node_id>
  2. 在源節點上聲明將往目標節點遷出Slot CLUSTER SETSLOT <slot> IMPORTING <source_node_id>
  3. 批量從源節點獲取KEY CLUSTER GETKEYSINSLOT <slot> <count>
  4. 將獲取的Key遷移到目標節點MIGRATE <target_ip> <target_port> <key_name> 0 <timeout>
  5. 重複步驟3,4直到所有數據遷移完畢
  6. 分別向雙方節點發送CLUSTER SETSLOT <slot> NODE <target_node_id>,該命令將會廣播給集羣其他節點,已經將Slot轉移到目標節點。
  7. 等待集羣狀態變爲OK

遷移過程並不會影響集羣的狀態,集羣可以正常提供數據讀寫服務:
當一個源節點受到一條已遷移數據命令時,源節點會發送一條ASK ip port 命令給客戶端,提示客戶端該數據所在數據槽已遷移到目標節點,客戶端會向MOVED命令一樣,重定向到目標節點上執行命令。

高可用

在Redis Cluster中,每個節點都應包含一個主節點和N個從節點,當主節點掛掉時,需要從節點選舉出一個從節點成爲主節點,繼續管理相應的數據槽。

redis的主節點選舉算法爲Raft算法

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章