節(jié)點(diǎn) | 處理槽位 |
---|---|
A | 0 - 5000 |
B | 5001 - 10000 |
C | 10001 - 16383 |
每個Redis實(shí)例會自己維護(hù)一份slot - Redis節(jié)點(diǎn)的映射關(guān)系,假設(shè)你在節(jié)點(diǎn)A上設(shè)置了某個key,但是這個key通過CRC16計算出來的槽位是由節(jié)點(diǎn)B維護(hù)的,那么就會提示你需要去節(jié)點(diǎn)B上進(jìn)行操作。
slot-to-node
不知道你思考過一個問題沒,如果Redis Cluster中的某個master節(jié)點(diǎn)掛了,它是如何保證集群自身的高可用的?如果這個時候我們集群需要擴(kuò)容節(jié)點(diǎn),它該負(fù)責(zé)哪些槽位呢?我們一個一個問題的來看一下。
我們開篇聊過,Redis Cluster可以很方便的進(jìn)行橫向擴(kuò)容,那當(dāng)新的節(jié)點(diǎn)加入進(jìn)來的時候,它是如何獲取對應(yīng)的slot的呢?
答案是通過reshard(重新分片)來實(shí)現(xiàn)。reshard可以將已經(jīng)分配給某個節(jié)點(diǎn)的任意數(shù)量的slot遷移給另一個節(jié)點(diǎn),在Redis內(nèi)部是由redis-trib負(fù)責(zé)執(zhí)行的。你可以理解為Redis其實(shí)已經(jīng)封裝好了所有的命令,而redis-trib則負(fù)責(zé)向獲取slot的節(jié)點(diǎn)和被轉(zhuǎn)移slot的節(jié)點(diǎn)發(fā)送命令來最終實(shí)現(xiàn)reshard。
假設(shè)我們需要向集群中加入一個D節(jié)點(diǎn),而此時集群內(nèi)已經(jīng)有A、B、C三個節(jié)點(diǎn)了。
此時redis-trib會向A、B、C三個節(jié)點(diǎn)發(fā)送遷移出槽位的請求,同時向D節(jié)點(diǎn)發(fā)送準(zhǔn)備導(dǎo)入槽位的請求,做好準(zhǔn)備之后A、B、C這三個源節(jié)點(diǎn)就開始執(zhí)行遷移,將對應(yīng)的slot所對應(yīng)的鍵值對遷移至目標(biāo)節(jié)點(diǎn)D。最后redis-trib會向集群中所有主節(jié)點(diǎn)發(fā)送槽位的變更信息。
Redis Cluster中保證集群高可用的思路和實(shí)現(xiàn)和Redis Sentinel如出一轍
簡單來說,針對A節(jié)點(diǎn),某一個節(jié)點(diǎn)認(rèn)為A宕機(jī)了,那么此時是主觀宕機(jī)。而如果集群內(nèi)超過半數(shù)的節(jié)點(diǎn)認(rèn)為A掛了, 那么此時A就會被標(biāo)記為客觀宕機(jī)。
一旦節(jié)點(diǎn)A被標(biāo)記為了客觀宕機(jī),集群就會開始執(zhí)行故障轉(zhuǎn)移。其余正常運(yùn)行的master節(jié)點(diǎn)會進(jìn)行投票選舉,從A節(jié)點(diǎn)的slave節(jié)點(diǎn)中選舉出一個,將其切換成新的master對外提供服務(wù)。當(dāng)某個slave獲得了超過半數(shù)的master節(jié)點(diǎn)投票,就成功當(dāng)選。
cluster-failover
當(dāng)選成功之后,新的master會執(zhí)行slaveof no one
來讓自己停止復(fù)制A節(jié)點(diǎn),使自己成為master。然后將A節(jié)點(diǎn)所負(fù)責(zé)處理的slot,全部轉(zhuǎn)移給自己,然后就會向集群發(fā)PONG消息來廣播自己的最新狀態(tài)。
按照一致性哈希的思想,如果某個節(jié)點(diǎn)掛了,那么就會沿著那個圓環(huán),按照順時針的順序找到遇到的第一個Redis實(shí)例。
而對于Redis Cluster,某個key它其實(shí)并不關(guān)心它最終要去到哪個節(jié)點(diǎn),他只關(guān)心他最終落到哪個slot上,無論你節(jié)點(diǎn)怎么去遷移,最終還是只需要找到對應(yīng)的slot,然后再找到slot關(guān)聯(lián)的節(jié)點(diǎn),最終就能夠找到最終的Redis實(shí)例了。
那這個PONG消息又是什么東西呢?別急,下面就會聊到。
這就是Redis Cluster各個節(jié)點(diǎn)之間交換數(shù)據(jù)、通信所采用的一種協(xié)議,叫做gossip。
gossip: 流言、八卦、小道消息
gossip是在1989年的論文上提出的,我看了一堆資料都說的是1987年發(fā)表的,但是文章里的時間明確是1989年1月份發(fā)表。
image-20201215100703648
感興趣的可以去看看Epidemic Algorithms for Replicated . Database Maintenance,在當(dāng)時提出gossip主要是為了解決在分布式數(shù)據(jù)庫中,各個副本節(jié)點(diǎn)的數(shù)據(jù)同步問題。但隨著技術(shù)的發(fā)展,gossip后續(xù)也被廣泛運(yùn)用于信息擴(kuò)散、故障探測等等。
Redis Cluster就是利用了gossip來實(shí)現(xiàn)自身的信息擴(kuò)散的。那使用gossip具體是如何通信的呢?
gossip
很簡單,就像圖里這樣。每個Redis節(jié)點(diǎn)每秒鐘都會向其他的節(jié)點(diǎn)發(fā)送PING,然后被PING的節(jié)點(diǎn)會回一個PONG。
Redis Cluster中,節(jié)點(diǎn)之間的消息類型有5種,分別是MEET、PING、PONG、FAIL和PUBLISH。這些消息分別傳遞了什么內(nèi)容呢?我簡單總結(jié)了一下。
消息類型 | 消息內(nèi)容 |
---|---|
MEET | 給某個節(jié)點(diǎn)發(fā)送MEET消息,請求接收消息的節(jié)點(diǎn)加入到集群中 |
PING | 每隔一秒鐘,選擇5個最久沒有通信的節(jié)點(diǎn),發(fā)送PING消息,檢測對應(yīng)的節(jié)點(diǎn)是否在線;同時還有一種策略是,如果某個節(jié)點(diǎn)的通信延遲大于了cluster-node-time的值的一半,就會立即給該節(jié)點(diǎn)發(fā)送PING消息,避免數(shù)據(jù)交換延遲過久 |
PONG | 當(dāng)節(jié)點(diǎn)接收到MEET或者PING消息之后,會回一個PONG消息給發(fā)送方,代表自己收到了MEET或者PING消息。同時,節(jié)點(diǎn)也可以主動的通過PONG消息向集群中廣播自己的信息,讓其他節(jié)點(diǎn)獲取到自己最新的屬性,就像完成了故障轉(zhuǎn)移之后新的master向集群發(fā)送PONG消息一樣 |
FAIL | 用于廣播自己的對某個節(jié)點(diǎn)的宕機(jī)判斷,假設(shè)當(dāng)前節(jié)點(diǎn)對A節(jié)點(diǎn)判斷為宕機(jī),就會立即向Redis Cluster廣播自己對于A節(jié)點(diǎn)的判斷,所有收到消息的節(jié)點(diǎn)就會對A節(jié)點(diǎn)做標(biāo)記 |
PUBLISH | 用于向指定的Channel發(fā)送消息,某個節(jié)點(diǎn)收到PUBLISH消息之后會直接在集群內(nèi)廣播,這樣一來,客戶端無論連接到任何節(jié)點(diǎn)都能夠訂閱這個Channel |
既然Redis Cluster選擇了gossip,那肯定存在一些gossip的優(yōu)點(diǎn),我們接下來簡單梳理一下。 gossip可以在O(logN) 輪就可以將信息傳播到所有的節(jié)點(diǎn),為什么是O(logN)呢?因?yàn)槊看蝡ing,當(dāng)前節(jié)點(diǎn)會帶上自己的信息外加整個Cluster的1/10數(shù)量的節(jié)點(diǎn)信息,一起發(fā)送出去。你可以簡單的把這個模型抽象為: 你轉(zhuǎn)發(fā)了一個特別有意思的文章到朋友圈,然后你的朋友們都覺得還不錯,于是就一傳十、十傳百這樣的散播出去了,這就是朋友圈的裂變傳播。 當(dāng)然,gossip仍然存在一些缺點(diǎn)。例如消息可能最終會經(jīng)過很多輪才能到達(dá)目標(biāo)節(jié)點(diǎn),而這可能會帶來較大的延遲。同時由于節(jié)點(diǎn)會隨機(jī)選出5個最久沒有通信的節(jié)點(diǎn),這可能會造成某一個節(jié)點(diǎn)同時收到n個重復(fù)的消息。 總的來說,Redis Cluster相當(dāng)于是把Redis的主從架構(gòu)和Sentinel集成到了一起,從Redis Cluster的高可用機(jī)制、判斷故障轉(zhuǎn)移以及執(zhí)行故障轉(zhuǎn)移的過程,都和主從、Sentinel相關(guān),這也是為什么我在之前的文章里說,主從是Redis高可用架構(gòu)的基石。 以上就是解析Redis Cluster原理的詳細(xì)內(nèi)容,更多關(guān)于Redis Cluster的資料請關(guān)注腳本之家其它相關(guān)文章!十一、使用gossip的優(yōu)劣
優(yōu)點(diǎn)
描述
擴(kuò)展性
網(wǎng)絡(luò)可以允許節(jié)點(diǎn)的任意增加和減少,新增加的節(jié)點(diǎn)的狀態(tài)最終會與其他節(jié)點(diǎn)一致。
容錯性
由于每個節(jié)點(diǎn)都持有一份完整元數(shù)據(jù),所以任何節(jié)點(diǎn)宕機(jī)都不會影響gossip的運(yùn)行
健壯性
與容錯性類似,由于所有節(jié)點(diǎn)都持有數(shù)據(jù),地位平臺,是一個去中心化的設(shè)計,任何節(jié)點(diǎn)都不會影響到服務(wù)的運(yùn)行
最終一致性
當(dāng)有新的信息需要傳遞時,消息可以快速的發(fā)送到所有的節(jié)點(diǎn),讓所有的節(jié)點(diǎn)都擁有最新的數(shù)據(jù)
十二、總結(jié)
標(biāo)簽:北京 果洛 楊凌 臺州 江蘇 吉安 朝陽 大慶
巨人網(wǎng)絡(luò)通訊聲明:本文標(biāo)題《解析Redis Cluster原理》,本文關(guān)鍵詞 解析,Redis,Cluster,原理,解析,;如發(fā)現(xiàn)本文內(nèi)容存在版權(quán)問題,煩請?zhí)峁┫嚓P(guān)信息告之我們,我們將及時溝通與處理。本站內(nèi)容系統(tǒng)采集于網(wǎng)絡(luò),涉及言論、版權(quán)與本站無關(guān)。