支撐微博億級社交平臺,小白也能玩轉Redis叢集(原理篇)

分散式系統架構發表於2019-10-21

Redis作為一款效能優異的記憶體資料庫,支撐著微博億級社交平臺,也成為很多網際網路公司的標配。這裡將以Redis Cluster叢集為核心,基於最新的Redis5版本,從原理再到實戰,玩轉Redis叢集

常見Redis叢集方案

在介紹Redis Cluster叢集方案之前,為了方便對比,先簡單瞭解一下業界常見的Redis叢集方案:

1 基於客戶端分片

支撐微博億級社交平臺,小白也能玩轉Redis叢集(原理篇)

Redis Sharding是Redis Cluster出來之前,業界普遍使用的多Redis例項叢集方法。其主要思想是基於雜湊演算法,根據Redis資料的key的雜湊值對資料進行分片,將資料對映到各自節點上

優點在於實現簡單,缺點在於當Redis叢集調整,每個客戶端都需要更新調整

2 基於代理伺服器分片

支撐微博億級社交平臺,小白也能玩轉Redis叢集(原理篇)

客戶端傳送請求到獨立部署代理元件,代理元件解析客戶端的資料,並將請求轉發至正確的節點,最後將結果回覆給客戶端

優點在於透明接入,容易叢集擴充套件,缺點在於多了一層代理轉發,效能有所損耗

3 Redis Sentinel(哨兵)

支撐微博億級社交平臺,小白也能玩轉Redis叢集(原理篇)

Redis Sentinel是官方從Redis 2.6版本提供的高可用方案,在Redis主從複製叢集的基礎上,增加Sentinel叢集監控整個Redis叢集。當Redis叢集master節點發生故障時,Sentinel進行故障切換,選舉出新的master,同時Sentinel本身支援高可用叢集部署

優點在於支援叢集高可用,高效能讀寫,缺點在於沒有實現資料分片,每個節點需要承載完整資料集,負載能力受當個Redis伺服器限制,僅支援通過增加機器記憶體實現垂直擴容,不支援水平擴充套件

Redis Cluster設計

1 整體設計

Redis Cluster 是 在 3.0 版本正式推出的高可用叢集方案,相比Redis Sentinel,Redis Cluster方案不需要額外部署Sentinel叢集,而是通過叢集內部通訊實現叢集監控,故障時主從切換;同時,支援內部基於雜湊實現資料分片,支援動態水平擴容

整體架構如下:

支撐微博億級社交平臺,小白也能玩轉Redis叢集(原理篇)

叢集中有多個主節點,每個主節點有多個從節點,主從節點間資料一致,最少需要3個主節點,每個主節點最少需要1個從節點

  • 高可用:當master節點故障時,自動主從切換
  • 高效能:主節點提供讀寫服務,從節點只讀服務,提高系統吞吐量
  • 可擴充套件性:叢集的資料分片儲存,主節點間資料各不同,各自維護對應資料,可以為叢集新增節點進行擴容,也可以下線部分節點進行水平縮容

2 資料分片

將整個資料集按照一定規則分配到多個節點上,稱為資料分片,Redis Cluster採用的分片方案是雜湊分片

支撐微博億級社交平臺,小白也能玩轉Redis叢集(原理篇)

基本原理如下: Redis Cluster首先定義了編號0 ~ 16383的區間,稱為槽,所有的鍵根據雜湊函式對映到0 ~ 16383整數槽內,計算公式:slot=CRC16(key)&16383。每一個節點負責維護一部分槽以及槽所對映的鍵值資料

槽是 Redis 叢集管理資料的基本單位,叢集擴容收縮就是槽和資料在節點之間的移動

槽與節點對映關係如下:

  • 每個叢集節點維護著一個16384 bit (2kB)的位陣列,每個bit對應相同編號的槽,用 0 / 1標識對於某個槽自己是否擁有
  • 叢集節點同時還維護著槽到叢集節點的對映,是由長度為16384,陣列下標代表槽編號,值為節點資訊的陣列

支撐微博億級社交平臺,小白也能玩轉Redis叢集(原理篇)

3 叢集擴容

Redis Cluster支援不影響叢集對外服務的情況下,對叢集進行動態擴容或縮容,當Redis 新節點加入現有叢集后,需要為其遷移槽和資料,確保遷移後每個節點負責相似數量的槽,使資料分佈均勻在各節點上

整個資料遷移涉及系列操作,Redis提供了叢集管理工具,包括基於Ruby的redis-trib.rb,還Redis5新提供的基於C語言redis-cli,下面的介紹以redis-cli為例

源節點將指定slot資料遷移到目標節點,基本流程如下:

支撐微博億級社交平臺,小白也能玩轉Redis叢集(原理篇)

  • (1) redis-cli設定目標節點指定slot狀態importing,讓目標節點準備遷入slot資料
  • (2) redis-cli設定源節點指定slot狀態migrating,讓讓源節點準備遷出slot的資料
  • (3) redis-cli批量遷移源節點指定slot中的資料到目標節點
  • (4) 資料遷移完後 redis-cli向叢集所有主節點通知槽被分配給目標節點,主節點更新slot與節點對映關係資訊

通常情況下,如果客戶端請求的資料不在節點上,節點會回覆 MOVED 重定向資訊,客戶端根據該資訊再請求正確的節點。對於正在遷移的slot資料,保證客戶端仍然能正常訪問的設計如下:

支撐微博億級社交平臺,小白也能玩轉Redis叢集(原理篇)

  • (1) 遷移完成後才更新slot與節點對映關係資訊,如果遷移進行中的對映資訊保持與遷移前一致
  • (2) 如果客戶端訪問源節點,訪問的key尚未遷出,則正常的處理該key
  • (3) 如果客戶端訪問源節點,訪問的key尚已遷出,源節點返回ASK重定向資訊
  • (4) 客戶端根據ASK 重定向異常提取出目標節點資訊,先向目標節點傳送ASKING命令請求操作,再執行鍵命令

ASK 和 MOVED 這2個重定向控制有如下區別:

  • ASK 重定向說明叢集正在進行 slot 資料遷移,客戶端無法知道什麼時候遷移完成,因此只能是臨時性的重定向,客戶端不會更新 slot 到 Redis 節點的對映快取。
  • MOVED 重定向說明鍵對應的slot 已經明確指定到新的節點,因此需要更新 slot 到 Redis 節點的對映快取

4 CAP取捨

CAP包括:一致性(Consistency)、可用性(Availability)、分割槽容錯性(Partition tolerance),系統如果不能在時限內達成資料一致性,就意味著發生了分割槽的情況,必須在C和A之間做出選擇

Redis Cluster選擇了AP架構,為了保證可用性,Redis並不保證強一致性,在特定條件下會出現資料不一致甚至丟失寫操作

支撐微博億級社交平臺,小白也能玩轉Redis叢集(原理篇)

第一個原因是:為了在效能和一致性上做出權衡,主從節點間資料同步是非同步複製的,當客戶端成功寫入master節點,master返回成功,master節點才將寫操作非同步複製給slave節點

另外一個原因是,當叢集傳送網路分割槽,叢集可能會分為兩部分:多數派和少數派,假如masterA節點位於少數派,如果網路分割槽發生時間較短,那麼叢集將會繼續正常運作;如果分割槽的時間足夠長,讓多數派中選舉為新的master替代matsterA,那麼分割槽期間寫入masterA的資料就丟失了

在網路分割槽期間, 客戶端可以向matsterA傳送寫命令的最大時間是有限制的, 這一時間限制稱為節點超時時間(cluster-node-timeout),是 Redis叢集的一個重要的配置選項

總結

至此,Redis Cluster叢集原理介紹到這裡,其實還有叢集通訊協議,記憶體,資料備份,主從複製等特性值得學習,是設計分散式系統的典範,有機會再展開介紹

下一篇《實戰篇》,介紹Redis Cluster的叢集實戰

參考

微博6年redis實踐 mp.weixin.qq.com/s/dBWIHwfmr…

Redis 官網介紹cluster設計說明 redis.io/topics/clus… redis.io/topics/clus…

支撐微博億級社交平臺,小白也能玩轉Redis叢集(原理篇)

相關文章