Redis集群高可用原理解析

大家好,我是IT修真院北京分院第31期的學員,一枚正直純潔善良的JAVA程序員。今天給大家分享一下,Redis集群高可用原理解析.

1.背景介紹

REDIS集群

Redis在3.0版正式引入了集群特性。Redis集群是一個分布式(distributed)、容錯(fault-tolerant)的 Redis內(nèi)存K/V服務(wù), 普通單機 Redis 使用的功能 僅是集群中功能的一個子集(subset)。Redis集群并不支持處理多個keys的命令,因為這需要在不同的節(jié)點間移動數(shù)據(jù),從而達不到像Redis那樣的性能,在高負載的情況下可能會導致不可預料的錯誤。

REDIS CLUSTER主要特性和設(shè)計

集群目標

(1)高性能和線性擴展,最大可以支撐到1000個節(jié)點;Cluster架構(gòu)中無Proxy層,Master與slave之間使用異步replication, 且不存在操作的merge。(即操作不能跨多個nodes,不存在merge層)?

(2)一定程度上保證writes的安全性,需要客戶端容忍一定程度的數(shù)據(jù)丟失:集群將會盡可能(best-effort)保存客戶端write操作的數(shù)據(jù);通常在failover期間,會有短暫時間內(nèi)的數(shù)據(jù)丟失(因為異步replication引起);當客戶端與少數(shù)派的節(jié)點處于網(wǎng)絡(luò)分區(qū)時(network partition),丟失數(shù)據(jù)的可能性會更高。(因為節(jié)點有效性檢測、failover需要更長的時間)

(3)可用性:只要集群中大多數(shù)master可達、且失效的master至少有一個slave可達時,集群都可以繼續(xù)提供服務(wù);同時“replicas migration”可以將那些擁有多個slaves的master的某個slave,遷移到?jīng)]有slave的master下,即將slaves的分布在整個集群相對平衡,盡力確保每個master都有一定數(shù)量的slave備份。

REDIS集群的幾個重要特征

(1).Redis 集群的分片特征在于將鍵空間分拆了16384個槽位,每一個節(jié)點負責其中一些槽位。 (2).Redis提供一定程度的可用性,可以在某個節(jié)點宕機或者不可達的情況下繼續(xù)處理命令. (3).Redis 集群中不存在中心(central)節(jié)點或者代理(proxy)節(jié)點, 集群的其中一個主要設(shè)計目標是達到線性可擴展性(linear scalability)。

集群客戶端連接集群中任一Redis Instance即可發(fā)送命令,當Redis Instance收到自己不負責的Slot的請求時,會將負責請求Key所在Slot的Redis Instance地址返回給客戶端,客戶端收到后自動將原請求重新發(fā)往這個地址,對外部透明。一個Key到底屬于哪個Slot由crc16(key) % 16384 決定。

REDIS數(shù)據(jù)切片

Redis 集群的鍵空間被分割為 16384 (2^14)個槽(slot), 集群的最大節(jié)點數(shù)量也是 16384 個(推薦的最大節(jié)點數(shù)量為 1000 個),同理每個主節(jié)點可以負責處理1到16384個槽位。當16384個槽位都有主節(jié)點負責處理時,集群進入“穩(wěn)定”上線狀態(tài),可以開始處理數(shù)據(jù)命令。當集群沒有處理穩(wěn)定狀態(tài)時,可以通過執(zhí)行重配置(reconfiguration)操作,使得每個哈希槽都只由一個節(jié)點進行處理。 重配置指的是將某個/某些槽從一個節(jié)點移動到另一個節(jié)點。一個主節(jié)點可以有任意多個從節(jié)點, 這些從節(jié)點用于在主節(jié)點發(fā)生網(wǎng)絡(luò)斷線或者節(jié)點失效時, 對主節(jié)點進行替換。 集群的使用公式HASH_SLOT=CRC16(key) mod 16384 計算key屬于哪個槽。CRC16其結(jié)果長度為16位。

REDIS集群節(jié)點

Redis 集群中的節(jié)點不僅要記錄鍵和值的映射,還需要記錄集群的狀態(tài),包括鍵到正確節(jié)點的映射。它還具有自動發(fā)現(xiàn)其他節(jié)點,識別工作不正常的節(jié)點,并在有需要時,在從節(jié)點中選舉出新的主節(jié)點的功能。為了執(zhí)行以上列出的任務(wù), 集群中的每個節(jié)點都與其他節(jié)點建立起了“集群連接(cluster bus)”, 該連接是一個 TCP 連接, 使用二進制協(xié)議進行通訊。 節(jié)點之間使用 Gossip 協(xié)議 來進行以下工作: (a).傳播(propagate)關(guān)于集群的信息,以此來發(fā)現(xiàn)新的節(jié)點; (b).向其他節(jié)點發(fā)送 PING 數(shù)據(jù)包,以此來檢查目標節(jié)點是否正常運作; (c).在特定事件發(fā)生時,發(fā)送集群信息. 除此之外, 集群連接還用于在集群中發(fā)布或訂閱信息。

集群節(jié)點不能前端代理命令請求, 所以客戶端應(yīng)該在節(jié)點返回 -MOVED或者 -ASK轉(zhuǎn)向(redirection)錯誤時, 自行將命令請求轉(zhuǎn)發(fā)至其他節(jié)點。 客戶端可以自由地向集群中的任何一個節(jié)點發(fā)送命令請求, 并可以在有需要時, 根據(jù)轉(zhuǎn)向錯誤所提供的信息, 將命令轉(zhuǎn)發(fā)至正確的節(jié)點, 所以在理論上來說, 客戶端是無須保存集群狀態(tài)信息的。但如果客戶端可以將鍵和節(jié)點之間的映射信息保存起來, 可以有效地減少可能出現(xiàn)的轉(zhuǎn)向次數(shù), 借此提升命令執(zhí)行的效率。 每個節(jié)點在集群中由一個獨一無二的 ID標識, 該 ID 是一個十六進制表示的 160 位隨機數(shù),在節(jié)點第一次啟動時由 /dev/urandom 生成。節(jié)點會將它的 ID 保存到配置文件, 只要這個配置文件不被刪除, 節(jié)點就會一直沿用這個 ID 。一個節(jié)點可以改變它的 IP 和端口號, 而不改變節(jié)點 ID 。 集群可以自動識別出IP/端口號的變化, 并將這一信息通過 Gossip協(xié)議廣播給其他節(jié)點知道。

2.知識剖析

GOSSIP協(xié)議

節(jié)點之間采用Gossip協(xié)議進行通信,Gossip協(xié)議就是指節(jié)點彼此之間不斷通信交換信息,當主從角色變化或新增節(jié)點,彼此通過ping/pong進行通信知道全部節(jié)點的最新狀態(tài)并達到集群同步. Gossip協(xié)議的主要職責就是信息交換,信息交換的載體就是節(jié)點之間彼此發(fā)送的Gossip消息,常用的Gossip消息有ping消息、pong消息、meet消息、fail消息. meet消息:用于通知新節(jié)點加入,消息發(fā)送者通知接收者加入到當前集群,meet消息通信完后,接收節(jié)點會加入到集群中,并進行周期性ping pong交換

ping消息:集群內(nèi)交換最頻繁的消息,集群內(nèi)每個節(jié)點每秒向其它節(jié)點發(fā)ping消息,用于檢測節(jié)點是在在線和狀態(tài)信息,ping消息發(fā)送封裝自身節(jié)點和其他節(jié)點的狀態(tài)數(shù)據(jù); pong消息,當接收到ping meet消息時,作為響應(yīng)消息返回給發(fā)送方,用來確認正常通信,pong消息也封閉了自身狀態(tài)數(shù)據(jù); fail消息:當節(jié)點判定集群內(nèi)的另一節(jié)點下線時,會向集群內(nèi)廣播一個fail消息,

消息解析流程

所有消息格式為:消息頭、消息體,消息頭包含發(fā)送節(jié)點自身狀態(tài)數(shù)據(jù)(比如節(jié)點ID、槽映射、節(jié)點角色、是否下線等),接收節(jié)點根據(jù)消息頭可以獲取到發(fā)送節(jié)點的相關(guān)數(shù)據(jù)。

選擇節(jié)點并發(fā)送PING消息

Gossip協(xié)議信息的交換機制具有天然的分布式特性,但ping,pong發(fā)送的頻率很高,可以實時得到其它節(jié)點的狀態(tài)數(shù)據(jù),但頻率高會加重帶寬和計算能力,因此每次都會有目的性地選擇一些節(jié)點; 但是節(jié)點選擇過少又會影響故障判斷的速度,redis集群的Gossip協(xié)議兼顧了這兩者的優(yōu)缺點,如下圖:

故障轉(zhuǎn)移

redis集群實現(xiàn)了高可用,當集群內(nèi)少量節(jié)點出現(xiàn)故障時,通過故障轉(zhuǎn)移可以保證集群正常對外提供服務(wù)。當集群里某個節(jié)點出現(xiàn)了問題,redis集群內(nèi)的節(jié)點通過ping pong消息發(fā)現(xiàn)節(jié)點是否健康,是否有故障,其實主要環(huán)節(jié)也包括了:主觀下線和客觀下線;主觀下線:指某個節(jié)點認為另一個節(jié)點不可用,即下線狀態(tài),當然這個狀態(tài)不是最終的故障判定,只能代表這個節(jié)點自身的意見,也有可能存在誤判;

下線流程: A,節(jié)點a發(fā)送ping消息給節(jié)點b ,如果通信正常將接收到pong消息,節(jié)點a更新最近一次與節(jié)點b的通信時間; B,如果節(jié)點a與節(jié)點b通信出現(xiàn)問題則斷開連接,下次會進行重連,如果一直通信失敗,則它們的最后通信時間將無法更新; 節(jié)點a內(nèi)的定時任務(wù)檢測到與節(jié)點b最后通信時間超過cluster_note-timeout時,更新本地對節(jié)點b的狀態(tài)為主觀下線(pfail) 客觀下線:指真正的下線,集群內(nèi)多個節(jié)點都認為該節(jié)點不可用,達成共識,將它下線,如果下線的節(jié)點為主節(jié)點,還要對它進行故障轉(zhuǎn)移 假如節(jié)點a標記節(jié)點b為主觀下線,一段時間后節(jié)點a通過消息把節(jié)點b的狀態(tài)發(fā)到其它節(jié)點,當節(jié)點c接受到消息并解析出消息體時,會發(fā)現(xiàn)節(jié)點b的pfail狀態(tài)時,會觸發(fā)客觀下線流程; 當下線為主節(jié)點時,此時redis集群為統(tǒng)計持有槽的主節(jié)點投票數(shù)是否達到一半,當下線報告統(tǒng)計數(shù)大于一半時,被標記為客觀下線狀態(tài)。

故障恢復: 故障主節(jié)點下線后,如果下線節(jié)點的是主節(jié)點,則需要在它的從節(jié)點中選一個替換它,保證集群的高可用;轉(zhuǎn)移過程如下: 1,資格檢查:檢查該從節(jié)點是否有資格替換故障主節(jié)點,如果此從節(jié)點與主節(jié)點斷開過通信,那么當前從節(jié)點不具體故障轉(zhuǎn)移; 2,準備選舉時間:當從節(jié)點符合故障轉(zhuǎn)移資格后,更新觸發(fā)故障選舉時間,只有到達該時間后才能執(zhí)行后續(xù)流程; 3,發(fā)起選舉:當?shù)竭_故障選舉時間時,進行選舉; 4,選舉投票:只有持有槽的主節(jié)點才有票,會處理故障選舉消息,投票過程其實是一個領(lǐng)導者選舉(選舉從節(jié)點為領(lǐng)導者)的過程,每個主節(jié)點只能投一張票給從節(jié)點,當從節(jié)點收集到足夠的選票(大于N/2+1)后,觸發(fā)替換主節(jié)點操作,撤銷原故障主節(jié)點的槽,委派給自己,并廣播自己的委派消息,通知集群內(nèi)所有節(jié)點。

數(shù)據(jù)遷移

當前集群有3個節(jié)點,槽默認是平均分的: 節(jié)點 A (6381)包含 0 到 5499號哈希槽. 節(jié)點 B (6382)包含5500 到 10999 號哈希槽. 節(jié)點 C (6383)包含11000 到 16383號哈希槽. 這種結(jié)構(gòu)很容易添加或者刪除節(jié)點. 比如如果我想新添加個節(jié)點D, 我需要從節(jié)點 A, B, C中得部分槽到D上. 如果我像移除節(jié)點A,需要將A中得槽移到B和C節(jié)點上,然后將沒有任何槽的A節(jié)點從集群中移除即可. 由于從一個節(jié)點將哈希槽移動到另一個節(jié)點并不會停止服務(wù),所以無論添加刪除或者改變某個節(jié)點的哈希槽的數(shù)量都不會造成集群不可用的狀態(tài).

數(shù)據(jù)遷移可以理解為slot(槽)和key的遷移,這個功能很重要,極大地方便了集群做線性擴展,以及實現(xiàn)平滑的擴容或縮容。 現(xiàn)在要將Master A節(jié)點中編號為1、2、3的slot遷移到Master B節(jié)點中,在slot遷移的中間狀態(tài)下,slot 1、2、3在Master A節(jié)點的狀態(tài)表現(xiàn)為MIGRATING(遷移),在Master B節(jié)點的狀態(tài)表現(xiàn)為IMPORTING(入口)。此時并不刷新node的映射關(guān)系

IMPORTING狀態(tài): 被遷移slot 在目標Master B節(jié)點中出現(xiàn)的一種狀態(tài),準備遷移slot從Mater A到Master B的時候,被遷移slot的狀態(tài)首先變?yōu)镮MPORTING狀態(tài)。 鍵空間遷移: 鍵空間遷移是指當滿足了slot遷移前提的情況下,通過相關(guān)命令將slot 1、2、3中的鍵空間從Master A節(jié)點轉(zhuǎn)移到Master B節(jié)點。此時刷新node的映射關(guān)系。

3.編碼實戰(zhàn)

4.常見問題

REDIS如何做持久化的?

bgsave做鏡像全量持久化,aof做增量持久化。因為bgsave會耗費較長時間,不夠?qū)崟r,在停機的時候會導致大量丟失數(shù)據(jù),所以需要aof來配合使用。在redis實例重啟時,會使用bgsave持久化文件重新構(gòu)建內(nèi)存,再使用aof重放近期的操作指令來實現(xiàn)完整恢復重啟之前的狀態(tài)。

REDIS集群的原理是什么?

Redis Sentinal著眼于高可用,在master宕機時會自動將slave提升為master,繼續(xù)提供服務(wù)。 Redis Cluster著眼于擴展性,在單個redis內(nèi)存不足時,使用Cluster進行分片存儲。

REDIS的同步機制了解么?

Redis可以使用主從同步,從從同步。第一次同步時,主節(jié)點做一次bgsave,并同時將后續(xù)修改操作記錄到內(nèi)存buffer,待完成后將rdb文件全量同步到復制節(jié)點,復制節(jié)點接受完成后將rdb鏡像加載到內(nèi)存。加載完成后,再通知主節(jié)點將期間修改的操作記錄同步到復制節(jié)點進行重放就完成了同步過程。

5.參考文獻

https://blog.csdn.net/tianpeng341204/article/details/78963850

https://blog.csdn.net/lidiya007/article/details/53289535

https://www.cnblogs.com/wxd0108/p/5798498.html

6.更多討論

鳴謝

感謝觀看,如有出錯,懇請指正

今天的分享就到這里啦,歡迎大家點贊、轉(zhuǎn)發(fā)、留言、拍磚~

????????技能樹.IT修真院

????????“我們相信人人都可以成為一個工程師,現(xiàn)在開始,找個師兄,帶你入門,掌控自己學習的節(jié)奏,學習的路上不再迷茫”。

????????這里是技能樹.IT修真院,成千上萬的師兄在這里找到了自己的學習路線,學習透明化,成長可見化,師兄1對1免費指導。快來與我一起學習吧~

我的邀請碼:17742750,或者你可以直接點擊此鏈接:http://www.jnshu.com/login/1/17742750

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 227,488評論 6 531
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 98,034評論 3 414
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 175,327評論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經(jīng)常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,554評論 1 307
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,337評論 6 404
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 54,883評論 1 321
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 42,975評論 3 439
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 42,114評論 0 286
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 48,625評論 1 332
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 40,555評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,737評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,244評論 5 355
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 43,973評論 3 345
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,362評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,615評論 1 280
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,343評論 3 390
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,699評論 2 370

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