Redis作為一款性能優異的內存數據庫,支撐着微博億級社交平台,也成為很多互聯網公司的標配。這里將以Redis Cluster集群為核心,基於最新的Redis5版本,從原理再到實戰,玩轉Redis集群
常見Redis集群方案
在介紹Redis Cluster集群方案之前,為了方便對比,先簡單了解一下業界常見的Redis集群方案:
1 基於客戶端分片
Redis Sharding是Redis Cluster出來之前,業界普遍使用的多Redis實例集群方法。其主要思想是基於哈希算法,根據Redis數據的key的哈希值對數據進行分片,將數據映射到各自節點上
優點在於實現簡單,缺點在於當Redis集群調整,每個客戶端都需要更新調整
2 基於代理服務器分片
客戶端發送請求到獨立部署代理組件,代理組件解析客戶端的數據,並將請求轉發至正確的節點,最后將結果回復給客戶端
優點在於透明接入,容易集群擴展,缺點在於多了一層代理轉發,性能有所損耗
3 Redis Sentinel(哨兵)
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集群,而是通過集群內部通信實現集群監控,故障時主從切換;同時,支持內部基於哈希實現數據分片,支持動態水平擴容
整體架構如下:
集群中有多個主節點,每個主節點有多個從節點,主從節點間數據一致,最少需要3個主節點,每個主節點最少需要1個從節點
- 高可用:當master節點故障時,自動主從切換
- 高性能:主節點提供讀寫服務,從節點只讀服務,提高系統吞吐量
- 可擴展性:集群的數據分片存儲,主節點間數據各不同,各自維護對應數據,可以為集群添加節點進行擴容,也可以下線部分節點進行水平縮容
2 數據分片
將整個數據集按照一定規則分配到多個節點上,稱為數據分片,Redis Cluster采用的分片方案是哈希分片
基本原理如下:
Redis Cluster首先定義了編號0 ~ 16383的區間,稱為槽,所有的鍵根據哈希函數映射到0 ~ 16383整數槽內,計算公式:slot=CRC16(key)&16383。每一個節點負責維護一部分槽以及槽所映射的鍵值數據
槽是 Redis 集群管理數據的基本單位,集群擴容收縮就是槽和數據在節點之間的移動
槽與節點映射關系如下:
- 每個集群節點維護着一個16384 bit (2kB)的位數組,每個bit對應相同編號的槽,用 0 / 1標識對於某個槽自己是否擁有
- 集群節點同時還維護着槽到集群節點的映射,是由長度為16384,數組下標代表槽編號,值為節點信息的數組
3 集群擴容
Redis Cluster支持不影響集群對外服務的情況下,對集群進行動態擴容或縮容,當Redis 新節點加入現有集群后,需要為其遷移槽和數據,確保遷移后每個節點負責相似數量的槽,使數據分布均勻在各節點上
整個數據遷移涉及系列操作,Redis提供了集群管理工具,包括基於Ruby的redis-trib.rb,還Redis5新提供的基於C語言redis-cli,下面的介紹以redis-cli為例
源節點將指定slot數據遷移到目標節點,基本流程如下:
- (1) redis-cli設置目標節點指定slot狀態importing,讓目標節點准備遷入slot數據
- (2) redis-cli設置源節點指定slot狀態migrating,讓讓源節點准備遷出slot的數據
- (3) redis-cli批量遷移源節點指定slot中的數據到目標節點
- (4) 數據遷移完后 redis-cli向集群所有主節點通知槽被分配給目標節點,主節點更新slot與節點映射關系信息
通常情況下,如果客戶端請求的數據不在節點上,節點會回復 MOVED 重定向信息,客戶端根據該信息再請求正確的節點。對於正在遷移的slot數據,保證客戶端仍然能正常訪問的設計如下:
- (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並不保證強一致性,在特定條件下會出現數據不一致甚至丟失寫操作
第一個原因是:為了在性能和一致性上做出權衡,主從節點間數據同步是異步復制的,當客戶端成功寫入master節點,master返回成功,master節點才將寫操作異步復制給slave節點
另外一個原因是,當集群發送網絡分區,集群可能會分為兩部分:多數派和少數派,假如masterA節點位於少數派,如果網絡分區發生時間較短,那么集群將會繼續正常運作;如果分區的時間足夠長,讓多數派中選舉為新的master替代matsterA,那么分區期間寫入masterA的數據就丟失了
在網絡分區期間, 客戶端可以向matsterA發送寫命令的最大時間是有限制的, 這一時間限制稱為節點超時時間(cluster-node-timeout),是 Redis集群的一個重要的配置選項
總結
至此,Redis Cluster集群原理介紹到這里,其實還有集群通信協議,內存,數據備份,主從復制等特性值得學習,是設計分布式系統的典范,有機會再展開介紹
下一篇,介紹Redis Cluster的集群實戰
參考
微博6年redis實踐
https://mp.weixin.qq.com/s/dBWIHwfmrs6Tt7INw-zSyA
Redis 官網介紹cluster設計說明
https://redis.io/topics/cluster-tutorial
https://redis.io/topics/cluster-spec