Redis集群模式高可用原理

什么是 Cluster 集群

Redis 集群是一種分布式數(shù)據(jù)庫方案塑悼,集群通過分片(sharding)來進(jìn)行數(shù)據(jù)管理(「分治思想」的一種實(shí)踐),并提供復(fù)制和故障轉(zhuǎn)移功能楷掉。

將數(shù)據(jù)劃分為 16384 的 slots厢蒜,每個節(jié)點(diǎn)負(fù)責(zé)一部分槽位。槽位的信息存儲于每個節(jié)點(diǎn)中烹植。

它是去中心化的斑鸦,如圖所示,該集群有三個 Redis 節(jié)點(diǎn)組成草雕,每個節(jié)點(diǎn)負(fù)責(zé)整個集群的一部分?jǐn)?shù)據(jù)巷屿,每個節(jié)點(diǎn)負(fù)責(zé)的數(shù)據(jù)多少可能不一樣。

三個節(jié)點(diǎn)相互連接組成一個對等的集群墩虹,它們之間通過 Gossip協(xié)議相互交互集群信息嘱巾,最后每個節(jié)點(diǎn)都保存著其他節(jié)點(diǎn)的 slots 分配情況。

集群安裝

一個 Redis 集群通常由多個節(jié)點(diǎn)(node)組成诫钓,在剛開始的時候旬昭,每個節(jié)點(diǎn)都是相互獨(dú)立的,它們都處于一個只包含自己的集群當(dāng)中菌湃,要組建一個真正可工作的集群问拘,我們必須將各個獨(dú)立的節(jié)點(diǎn)連接起來,構(gòu)成一個包含多個節(jié)點(diǎn)的集群。

連接各個節(jié)點(diǎn)的工作可以通過 CLUSTER MEET 命令完成:CLUSTER MEET <ip> <port> 骤坐。

向一個節(jié)點(diǎn) node 發(fā)送 CLUSTER MEET 命令绪杏,可以讓 node 節(jié)點(diǎn)與 ip 和 port 所指定的節(jié)點(diǎn)進(jìn)行握手(handshake),當(dāng)握手成功時纽绍,node 節(jié)點(diǎn)就會將 ip 和 port 所指定的節(jié)點(diǎn)添加到 node 節(jié)點(diǎn)當(dāng)前所在的集群中蕾久。

Cluster 實(shí)現(xiàn)原理

Redis 3.0 開始,官方提供了 Redis Cluster 方案實(shí)現(xiàn)了切片集群拌夏,該方案就實(shí)現(xiàn)了數(shù)據(jù)和實(shí)例的規(guī)則腔彰。Redis Cluster 方案采用哈希槽(Hash Slot,接下來我會直接稱之為 Slot)辖佣,來處理數(shù)據(jù)和實(shí)例之間的映射關(guān)系。

將數(shù)據(jù)分成多份存在不同實(shí)例上

集群的整個數(shù)據(jù)庫被分為 16384 個槽(slot)搓逾,數(shù)據(jù)庫中的每個鍵都屬于這 16384 個槽的其中一個卷谈,集群中的每個節(jié)點(diǎn)可以處理 0 個或最多 16384 個槽。

Key 與哈希槽映射過程可以分為兩大步驟:
1霞篡、根據(jù)鍵值對的 key世蔗,使用 CRC16 算法,計算出一個 16 bit 的值朗兵;
2污淋、將 16 bit 的值對 16384 執(zhí)行取模,得到 0 ~ 16383 的數(shù)表示 key 對應(yīng)的哈希槽余掖。

哈希槽與 Redis 實(shí)例映射
通過 cluster create 創(chuàng)建寸爆,Redis 會自動將 16384 個 哈希槽平均分布在集群實(shí)例上,比如 N 個節(jié)點(diǎn)盐欺,每個節(jié)點(diǎn)上的哈希槽數(shù) = 16384 / N 個赁豆。

可以使用 cluster addslots 命令,手動指定每個實(shí)例上的哈希槽個數(shù)冗美。


故障檢測
Redis 集群節(jié)點(diǎn)采用 Gossip 協(xié)議來廣播自己的狀態(tài)以及自己對整個集群認(rèn)知的改變魔种。比如一個節(jié)點(diǎn)發(fā)現(xiàn)某個節(jié)點(diǎn)失聯(lián)了 (PFail),它會將這條信息向整個集群廣播粉洼,其它節(jié)點(diǎn)也就可以收到這點(diǎn)失聯(lián)信息节预。

如果一個節(jié)點(diǎn)收到了某個節(jié)點(diǎn)失聯(lián)的數(shù)量 (PFail Count) 已經(jīng)達(dá)到了集群的大多數(shù),就可以標(biāo)記該節(jié)點(diǎn)為確定下線狀態(tài) (Fail)属韧,然后向整個集群廣播安拟,強(qiáng)迫其它節(jié)點(diǎn)也接收該節(jié)點(diǎn)已經(jīng)下線的事實(shí),并立即對該失聯(lián)節(jié)點(diǎn)進(jìn)行主從切換挫剑。

故障轉(zhuǎn)移
當(dāng)一個 Slave 發(fā)現(xiàn)自己的主節(jié)點(diǎn)進(jìn)入已下線狀態(tài)后去扣,從節(jié)點(diǎn)將開始對下線的主節(jié)點(diǎn)進(jìn)行故障轉(zhuǎn)移。
1、從下線的 Master 及節(jié)點(diǎn)的 Slave 節(jié)點(diǎn)列表選擇一個節(jié)點(diǎn)成為新主節(jié)點(diǎn)愉棱。
2唆铐、新主節(jié)點(diǎn)會撤銷所有對已下線主節(jié)點(diǎn)的 slot 指派,并將這些 slots 指派給自己奔滑。
3艾岂、新的主節(jié)點(diǎn)向集群廣播一條 PONG 消息,這條 PONG 消息可以讓集群中的其他節(jié)點(diǎn)立即知道這個節(jié)點(diǎn)已經(jīng)由從節(jié)點(diǎn)變成了主節(jié)點(diǎn)朋其,并且這個主節(jié)點(diǎn)已經(jīng)接管了原本由已下線節(jié)點(diǎn)負(fù)責(zé)處理的槽王浴。
4、新的主節(jié)點(diǎn)開始接收處理槽有關(guān)的命令請求梅猿,故障轉(zhuǎn)移完成氓辣。

跟哨兵類似,兩者都是基于 Raft 算法來實(shí)現(xiàn)的袱蚓,流程如圖所示:


客戶端如何定位數(shù)據(jù)所在實(shí)例

Redis 實(shí)例會將自己的哈希槽信息通過 Gossip 協(xié)議發(fā)送給集群中其他的實(shí)例钞啸,實(shí)現(xiàn)了哈希槽分配信息的擴(kuò)散。

這樣喇潘,集群中的每個實(shí)例都有所有哈希槽與實(shí)例之間的映射關(guān)系信息体斩。

在切片數(shù)據(jù)的時候是將 key 通過 CRC16 計算出一個值再對 16384 取模得到對應(yīng)的 Slot,這個計算任務(wù)可以在客戶端上執(zhí)行發(fā)送請求的時候執(zhí)行颖低。

但是絮吵,定位到槽以后還需要進(jìn)一步定位到該 Slot 所在 Redis 實(shí)例。

當(dāng)客戶端連接任何一個實(shí)例忱屑,實(shí)例就將哈希槽與實(shí)例的映射關(guān)系響應(yīng)給客戶端蹬敲,客戶端就會將哈希槽與實(shí)例映射信息緩存在本地。

當(dāng)客戶端請求時想幻,會計算出鍵所對應(yīng)的哈希槽粱栖,在通過本地緩存的哈希槽實(shí)例映射信息定位到數(shù)據(jù)所在實(shí)例上,再將請求發(fā)送給對應(yīng)的實(shí)例脏毯。

重新分配哈希槽
哈希槽與實(shí)例之間的映射關(guān)系由于新增實(shí)例或者負(fù)載均衡重新分配導(dǎo)致改變了,集群中的實(shí)例通過 Gossip 協(xié)議互相傳遞消息獲取最新的哈希槽分配信息闹究,但是,客戶端無法感知食店。

Redis Cluster 提供了重定向機(jī)制:客戶端將請求發(fā)送到實(shí)例上渣淤,這個實(shí)例沒有相應(yīng)的數(shù)據(jù),該 Redis 實(shí)例會告訴客戶端將請求發(fā)送到其他的實(shí)例上吉嫩。

Redis 如何告知客戶端重定向訪問新實(shí)例呢价认?

分為兩種情況:MOVED 錯誤、ASK 錯誤自娩。

MOVED 錯誤
MOVED 錯誤(負(fù)載均衡用踩,數(shù)據(jù)已經(jīng)遷移到其他實(shí)例上):當(dāng)客戶端將一個鍵值對操作請求發(fā)送給某個實(shí)例,而這個鍵所在的槽并非由自己負(fù)責(zé)的時候,該實(shí)例會返回一個 MOVED 錯誤指引轉(zhuǎn)向正在負(fù)責(zé)該槽的節(jié)點(diǎn)脐彩。

同時碎乃,客戶端還會更新本地緩存,將該 slot 與 Redis 實(shí)例對應(yīng)關(guān)系更新正確惠奸。

ASK 錯誤
如果某個 slot 的數(shù)據(jù)比較多梅誓,部分遷移到新實(shí)例,還有一部分沒有遷移咋辦佛南?

如果請求的 key 在當(dāng)前節(jié)點(diǎn)找到就直接執(zhí)行命令梗掰,否則時候就需要 ASK 錯誤響應(yīng)了,槽部分遷移未完成的情況下嗅回,如果需要訪問的 key 所在 Slot 正在從從 實(shí)例 1 遷移到 實(shí)例 2及穗,實(shí)例 1 會返回客戶端一條 ASK 報錯信息:客戶端請求的 key 所在的哈希槽正在遷移到實(shí)例 2 上,你先給實(shí)例 2 發(fā)送一個 ASKING 命令绵载,接著發(fā)發(fā)送操作命令拥坛。

集群可以設(shè)置多大?

Redis 官方給的 Redis Cluster 的規(guī)模上線是 1000 個實(shí)例尘分。

到底是什么限制了集群規(guī)模呢?關(guān)鍵在于實(shí)例間的通信開銷丸氛,Cluster 集群中的每個實(shí)例都保存所有哈希槽與實(shí)例對應(yīng)關(guān)系信息(Slot 映射到節(jié)點(diǎn)的表)培愁,以及自身的狀態(tài)信息。

在集群之間每個實(shí)例通過 Gossip協(xié)議傳播節(jié)點(diǎn)的數(shù)據(jù)缓窜,Gossip 協(xié)議工作原理大概如下:

1定续、從集群中隨機(jī)選擇一些實(shí)例按照一定的頻率發(fā)送 PING 消息發(fā)送給挑選出來的實(shí)例,用于檢測實(shí)例狀態(tài)以及交換彼此的信息禾锤。PING 消息中封裝了發(fā)送者自身的狀態(tài)信息私股、部分其他實(shí)例的狀態(tài)信息、Slot 與實(shí)例映射表信息恩掷。
2倡鲸、實(shí)例接收到 PING 消息后,響應(yīng) PONG 消息黄娘,消息包含的信息跟 PING 消息一樣峭状。

集群之間通過 Gossip協(xié)議可以在一段時間之后每個實(shí)例都能獲取其他所有實(shí)例的狀態(tài)信息。

所以在有新節(jié)點(diǎn)加入逼争,節(jié)點(diǎn)故障优床,Slot 映射變更都可以通過 PING,PONG 的消息傳播完成集群狀態(tài)在每個實(shí)例的傳播同步誓焦。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末胆敞,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌移层,老刑警劉巖仍翰,帶你破解...
    沈念sama閱讀 206,602評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異幽钢,居然都是意外死亡歉备,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,442評論 2 382
  • 文/潘曉璐 我一進(jìn)店門匪燕,熙熙樓的掌柜王于貴愁眉苦臉地迎上來蕾羊,“玉大人,你說我怎么就攤上這事帽驯」暝伲” “怎么了?”我有些...
    開封第一講書人閱讀 152,878評論 0 344
  • 文/不壞的土叔 我叫張陵尼变,是天一觀的道長利凑。 經(jīng)常有香客問我,道長嫌术,這世上最難降的妖魔是什么哀澈? 我笑而不...
    開封第一講書人閱讀 55,306評論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮度气,結(jié)果婚禮上割按,老公的妹妹穿的比我還像新娘。我一直安慰自己磷籍,他們只是感情好适荣,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,330評論 5 373
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著院领,像睡著了一般弛矛。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上比然,一...
    開封第一講書人閱讀 49,071評論 1 285
  • 那天丈氓,我揣著相機(jī)與錄音,去河邊找鬼强法。 笑死扒寄,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的拟烫。 我是一名探鬼主播该编,決...
    沈念sama閱讀 38,382評論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼硕淑!你這毒婦竟也來了课竣?” 一聲冷哼從身側(cè)響起嘉赎,我...
    開封第一講書人閱讀 37,006評論 0 259
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎于樟,沒想到半個月后公条,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,512評論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡迂曲,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,965評論 2 325
  • 正文 我和宋清朗相戀三年靶橱,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片路捧。...
    茶點(diǎn)故事閱讀 38,094評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡关霸,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出杰扫,到底是詐尸還是另有隱情队寇,我是刑警寧澤,帶...
    沈念sama閱讀 33,732評論 4 323
  • 正文 年R本政府宣布章姓,位于F島的核電站佳遣,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏凡伊。R本人自食惡果不足惜零渐,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,283評論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望系忙。 院中可真熱鬧相恃,春花似錦、人聲如沸笨觅。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,286評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽箱硕。三九已至唇礁,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間苍苞,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,512評論 1 262
  • 我被黑心中介騙來泰國打工狼纬, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留羹呵,地道東北人。 一個月前我還...
    沈念sama閱讀 45,536評論 2 354
  • 正文 我出身青樓疗琉,卻偏偏與公主長得像冈欢,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子盈简,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,828評論 2 345

推薦閱讀更多精彩內(nèi)容