Redis作為一款性能優(yōu)異的內(nèi)存數(shù)據(jù)庫,支撐著眾多億級流量平臺,也成為很多互聯(lián)網(wǎng)公司的標(biāo)配。這里將以Redis Cluster集群為核心,基于最新的Redis5版本,從原理再到實戰(zhàn),玩轉(zhuǎn)Redis集群
常見Redis集群方案
在介紹Redis Cluster集群方案之前,為了方便對比,先簡單了解一下業(yè)界常見的Redis集群方案:
1 基于客戶端分片
Redis Sharding是Redis Cluster出來之前,業(yè)界普遍使用的多Redis實例集群方法。其主要思想是基于哈希算法,根據(jù)Redis數(shù)據(jù)的key的哈希值對數(shù)據(jù)進(jìn)行分片,將數(shù)據(jù)映射到各自節(jié)點上
優(yōu)點在于實現(xiàn)簡單,缺點在于當(dāng)Redis集群調(diào)整,每個客戶端都需要更新調(diào)整
2 基于代理服務(wù)器分片
客戶端發(fā)送請求到獨立部署代理組件,代理組件解析客戶端的數(shù)據(jù),并將請求轉(zhuǎn)發(fā)至正確的節(jié)點,最后將結(jié)果回復(fù)給客戶端
優(yōu)點在于透明接入,容易集群擴(kuò)展,缺點在于多了一層代理轉(zhuǎn)發(fā),性能有所損耗
3 Redis Sentinel(哨兵)
Redis Sentinel是官方從Redis 2.6版本提供的高可用方案,在Redis主從復(fù)制集群的基礎(chǔ)上,增加Sentinel集群監(jiān)控整個Redis集群。當(dāng)Redis集群master節(jié)點發(fā)生故障時,Sentinel進(jìn)行故障切換,選舉出新的master,同時Sentinel本身支持高可用集群部署
優(yōu)點在于支持集群高可用,高性能讀寫,缺點在于沒有實現(xiàn)數(shù)據(jù)分片,每個節(jié)點需要承載完整數(shù)據(jù)集,負(fù)載能力受當(dāng)個Redis服務(wù)器限制,僅支持通過增加機(jī)器內(nèi)存實現(xiàn)垂直擴(kuò)容,不支持水平擴(kuò)展
Redis Cluster設(shè)計
1 整體設(shè)計
Redis Cluster 是 在 3.0 版本正式推出的高可用集群方案,相比Redis Sentinel,Redis Cluster方案不需要額外部署Sentinel集群,而是通過集群內(nèi)部通信實現(xiàn)集群監(jiān)控,故障時主從切換;同時,支持內(nèi)部基于哈希實現(xiàn)數(shù)據(jù)分片,支持動態(tài)水平擴(kuò)容
整體架構(gòu)如下:
集群中有多個主節(jié)點,每個主節(jié)點有多個從節(jié)點,主從節(jié)點間數(shù)據(jù)一致,最少需要3個主節(jié)點,每個主節(jié)點最少需要1個從節(jié)點
高可用:當(dāng)master節(jié)點故障時,自動主從切換
高性能:主節(jié)點提供讀寫服務(wù),從節(jié)點只讀服務(wù),提高系統(tǒng)吞吐量
可擴(kuò)展性:集群的數(shù)據(jù)分片存儲,主節(jié)點間數(shù)據(jù)各不同,各自維護(hù)對應(yīng)數(shù)據(jù),可以為集群添加節(jié)點進(jìn)行擴(kuò)容,也可以下線部分節(jié)點進(jìn)行水平縮容
2 數(shù)據(jù)分片
將整個數(shù)據(jù)集按照一定規(guī)則分配到多個節(jié)點上,稱為數(shù)據(jù)分片,Redis Cluster采用的分片方案是哈希分片
基本原理如下:Redis Cluster首先定義了編號0 ~ 16383的區(qū)間,稱為槽,所有的鍵根據(jù)哈希函數(shù)映射到0 ~ 16383整數(shù)槽內(nèi),計算公式:slot=CRC16(key)&16383。每一個節(jié)點負(fù)責(zé)維護(hù)一部分槽以及槽所映射的鍵值數(shù)據(jù)
槽是 Redis 集群管理數(shù)據(jù)的基本單位,集群擴(kuò)容收縮就是槽和數(shù)據(jù)在節(jié)點之間的移動
槽與節(jié)點映射關(guān)系如下:
每個集群節(jié)點維護(hù)著一個16384 bit (2kB)的位數(shù)組,每個bit對應(yīng)相同編號的槽,用 0 / 1標(biāo)識對于某個槽自己是否擁有
集群節(jié)點同時還維護(hù)著槽到集群節(jié)點的映射,是由長度為16384,數(shù)組下標(biāo)代表槽編號,值為節(jié)點信息的數(shù)組

3 集群擴(kuò)容
Redis Cluster支持不影響集群對外服務(wù)的情況下,對集群進(jìn)行動態(tài)擴(kuò)容或縮容,當(dāng)Redis 新節(jié)點加入現(xiàn)有集群后,需要為其遷移槽和數(shù)據(jù),確保遷移后每個節(jié)點負(fù)責(zé)相似數(shù)量的槽,使數(shù)據(jù)分布均勻在各節(jié)點上
整個數(shù)據(jù)遷移涉及系列操作,Redis提供了集群管理工具,包括基于Ruby的redis-trib.rb,還Redis5新提供的基于C語言redis-cli,下面的介紹以redis-cli為例
源節(jié)點將指定slot數(shù)據(jù)遷移到目標(biāo)節(jié)點,基本流程如下:
(1) redis-cli設(shè)置目標(biāo)節(jié)點指定slot狀態(tài)importing,讓目標(biāo)節(jié)點準(zhǔn)備遷入slot數(shù)據(jù)
(2) redis-cli設(shè)置源節(jié)點指定slot狀態(tài)migrating,讓讓源節(jié)點準(zhǔn)備遷出slot的數(shù)據(jù)
(3) redis-cli批量遷移源節(jié)點指定slot中的數(shù)據(jù)到目標(biāo)節(jié)點
(4) 數(shù)據(jù)遷移完后 redis-cli向集群所有主節(jié)點通知槽被分配給目標(biāo)節(jié)點,主節(jié)點更新slot與節(jié)點映射關(guān)系信息
通常情況下,如果客戶端請求的數(shù)據(jù)不在節(jié)點上,節(jié)點會回復(fù) MOVED 重定向信息,客戶端根據(jù)該信息再請求正確的節(jié)點。對于正在遷移的slot數(shù)據(jù),保證客戶端仍然能正常訪問的設(shè)計如下:
(1) 遷移完成后才更新slot與節(jié)點映射關(guān)系信息,如果遷移進(jìn)行中的映射信息保持與遷移前一致
(2) 如果客戶端訪問源節(jié)點,訪問的key尚未遷出,則正常的處理該key
(3) 如果客戶端訪問源節(jié)點,訪問的key尚已遷出,源節(jié)點返回ASK重定向信息
(4) 客戶端根據(jù)ASK 重定向異常提取出目標(biāo)節(jié)點信息,先向目標(biāo)節(jié)點發(fā)送ASKING命令請求操作,再執(zhí)行鍵命令
ASK 和 MOVED 這2個重定向控制有如下區(qū)別:
ASK 重定向說明集群正在進(jìn)行 slot 數(shù)據(jù)遷移,客戶端無法知道什么時候遷移完成,因此只能是臨時性的重定向,客戶端不會更新 slot 到 Redis 節(jié)點的映射緩存。
MOVED 重定向說明鍵對應(yīng)的slot 已經(jīng)明確指定到新的節(jié)點,因此需要更新 slot 到 Redis 節(jié)點的映射緩存
4 CAP取舍
CAP包括:一致性(Consistency)、可用性(Availability)、分區(qū)容錯性(Partition tolerance),系統(tǒng)如果不能在時限內(nèi)達(dá)成數(shù)據(jù)一致性,就意味著發(fā)生了分區(qū)的情況,必須在C和A之間做出選擇
Redis Cluster選擇了CA架構(gòu),為了保證可用性,Redis并不保證強(qiáng)一致性,在特定條件下會出現(xiàn)數(shù)據(jù)不一致甚至丟失寫操作
第一個原因是:為了在性能和一致性上做出權(quán)衡,主從節(jié)點間數(shù)據(jù)同步是異步復(fù)制的,當(dāng)客戶端成功寫入master節(jié)點,master返回成功,master節(jié)點才將寫操作異步復(fù)制給slave節(jié)點
另外一個原因是,當(dāng)集群發(fā)送網(wǎng)絡(luò)分區(qū),集群可能會分為兩部分:多數(shù)派和少數(shù)派,假如masterA節(jié)點位于少數(shù)派,如果網(wǎng)絡(luò)分區(qū)發(fā)生時間較短,那么集群將會繼續(xù)正常運(yùn)作;如果分區(qū)的時間足夠長,讓多數(shù)派中選舉為新的master替代matsterA,那么分區(qū)期間寫入masterA的數(shù)據(jù)就丟失了
在網(wǎng)絡(luò)分區(qū)期間, 客戶端可以向matsterA發(fā)送寫命令的最大時間是有限制的, 這一時間限制稱為節(jié)點超時時間(cluster-node-timeout),是 Redis集群的一個重要的配置選項
總結(jié)
至此,Redis Cluster集群原理介紹到這里,其實還有集群通信協(xié)議,內(nèi)存,數(shù)據(jù)備份,主從復(fù)制等特性值得學(xué)習(xí),是設(shè)計分布式系統(tǒng)的典范,有機(jī)會再展開介紹
下一篇,介紹Redis Cluster的集群實戰(zhàn)