老司機帶你玩轉(zhuǎn)面試(5):Redis 集群模式 Redis Cluster

image

前文回顧

建議前面文章沒看過的同學先看下前面的文章:

「老司機帶你玩轉(zhuǎn)面試(1):緩存中間件 Redis 基礎(chǔ)知識以及數(shù)據(jù)持久化」

「老司機帶你玩轉(zhuǎn)面試(2):Redis 過期策略以及緩存雪崩庭呜、擊穿、穿透」

「老司機帶你玩轉(zhuǎn)面試(3):Redis 高可用之主從模式」

「老司機帶你玩轉(zhuǎn)面試(4):Redis 高可用之哨兵模式」

簡介

之前介紹的 Redis 的高可用方案:主從模式或者說哨兵模式峡迷,都只是在解決高可用的問題装诡,比如說主從模式解決了讀高可用润脸,哨兵模式解決了寫高可用怔球。

如果我們需要緩存的數(shù)據(jù)量比較少,幾個 G 足夠用了驼抹,那么這兩種方案的高可用模式完全可以滿足需求桑孩,一個 master 對多個 salve ,需要幾個 salve 跟讀的吞吐量相關(guān)框冀,然后再搞一個 sentinel 集群去保證 Redis 主從模式的高可用流椒。

但是如果我們有大量的數(shù)據(jù)需要進緩存,單機的存儲容量無法滿足的時候明也,怎么辦宣虾?

這時,需要用到分布式緩存温数,就在幾年前绣硝,想用分布式緩存還得借助中間件來實現(xiàn),比如當時風靡一時的 codis 撑刺,或者說還有 twemproxy 鹉胖。在使用上,我們對 Redis 中間件進行讀寫操作够傍, Redis 中間件負責將我們的數(shù)據(jù)分布式的存儲在多臺機器上的 Redis 實例中甫菠。

而 Redis 也是不斷在發(fā)展的,終于在 3.0 的版本中(其實對現(xiàn)在來講也是比較早的版本了冕屯,現(xiàn)在的版本都 6.0 了)寂诱,原生支持了集群模式。

可以做到在多臺機器上安聘,部署多個 Redis 實例痰洒,每個實例存儲一部分的數(shù)據(jù),同時每個 Redis 主實例可以掛載 Redis 從實例搞挣,實現(xiàn)了 Redis 主實例掛了带迟,會自動切換到 Redis 從實例上來。

除了實現(xiàn)了分布式存儲以外囱桨,還順便實現(xiàn)了高可用仓犬。

分布式尋址算法

Redis Cluster 的數(shù)據(jù)是分布式存儲的,這就必然會引發(fā)一個問題舍肠,假如我有 3 個節(jié)點搀继,我如何知道一個 key 是存在這 3 個節(jié)點的哪一個節(jié)點上,取數(shù)的時候如何準確的找到對應(yīng)的節(jié)點將數(shù)據(jù)取出來翠语?這就要用到分布式尋址算法了叽躯。

常見的分布式尋址算法有兩種:

  • hash 算法
  • 一致性 hash 算法

hash 算法

hash 算法是對 key 進行 hash 運算后取值,然后對節(jié)點的數(shù)量取模肌括。

接著將 key 存入對應(yīng)的節(jié)點点骑,但是,一旦其中某個節(jié)點宕機,所有的請求過來黑滴,都會基于最新的存活的節(jié)點數(shù)量進行取模運算憨募,這就會導(dǎo)致大多數(shù)的請求無法拿到緩存數(shù)據(jù)。

舉個例子袁辈,一開始我有 3 個節(jié)點菜谣,這時大家正常的取模運算將數(shù)據(jù)基本均勻的存在了 3 個節(jié)點上,突然宕機了一臺晚缩,現(xiàn)在只剩下 2 個有效的節(jié)點了尾膊,這時所有的運算都會基于最新的 2 個節(jié)點進行取模運算,原來的 key 對 2 進行取模運算后荞彼,顯然和對 3 進行取模運算得到的結(jié)果是不一樣的冈敛。

結(jié)果是大量的數(shù)據(jù)請求會直接打在 DB 上,這是不可容忍的卿泽。

一致性 hash 算法

一致性 hash 算法將整個 hash 值空間組織成一個虛擬的圓環(huán)莺债,整個空間按順時針方向組織,下一步將各個 master 節(jié)點(使用服務(wù)器的 ip 或主機名)進行 hash签夭。這樣就能確定每個節(jié)點在其哈希環(huán)上的位置。

來看一個經(jīng)典的一致性 hash 算法的環(huán)狀示意圖:

image

來了一個 key椎侠,首先計算 hash 值第租,并確定此數(shù)據(jù)在環(huán)上的位置,從此位置沿環(huán)順時針「行走」我纪,遇到的第一個 master 節(jié)點就是 key 所在位置慎宾。

在一致性哈希算法中,如果一個節(jié)點掛了浅悉,受影響的數(shù)據(jù)僅僅是此節(jié)點到環(huán)空間前一個節(jié)點(沿著逆時針方向行走遇到的第一個節(jié)點)之間的數(shù)據(jù)趟据,其它不受影響。增加一個節(jié)點也同理术健。

一致性哈希算法在節(jié)點太少時汹碱,容易因為節(jié)點分布不均勻而造成緩存熱點的問題。為了解決這種熱點問題荞估,一致性 hash 算法引入了虛擬節(jié)點機制咳促,即對每一個節(jié)點計算多個 hash,每個計算結(jié)果位置都放置一個虛擬節(jié)點勘伺。這樣就實現(xiàn)了數(shù)據(jù)的均勻分布跪腹,負載均衡。

Redis Cluster 的 hash slot 算法

Redis Cluster 的實現(xiàn)方案十分的聰明飞醉,它的分區(qū)方式采用了虛擬槽分區(qū)冲茸。

Redis Cluster 首先會預(yù)設(shè)虛擬槽,每個槽就相當于一個數(shù)字,有一定范圍轴术,每個槽映射一個數(shù)據(jù)子集蹲盘。

Redis Cluster中預(yù)設(shè)虛擬槽的范圍為 0 到 16383

  1. Redis Cluster 會把 16384 個槽按照節(jié)點數(shù)量進行平均分配,由節(jié)點進行管理膳音。
  2. 當一個 key 過來的時候召衔,會對這個 key 按照 CRC16 規(guī)則進行 hash 運算。
  3. 把 hash 結(jié)果對 16383 進行取余祭陷。
  4. 把余數(shù)發(fā)送給 Redis 節(jié)點苍凛。
  5. 節(jié)點接收到數(shù)據(jù),驗證是否在自己管理的槽編號的范圍:
    1. 如果在自己管理的槽編號范圍內(nèi)兵志,則把數(shù)據(jù)保存到數(shù)據(jù)槽中醇蝴,然后返回執(zhí)行結(jié)果。
    2. 如果在自己管理的槽編號范圍外想罕,則會把數(shù)據(jù)發(fā)送給正確的節(jié)點悠栓,由正確的節(jié)點來把數(shù)據(jù)保存在對應(yīng)的槽中。

注意:Redis Cluster 的節(jié)點之間會共享消息按价,每個節(jié)點都會知道是哪個節(jié)點負責哪個范圍內(nèi)的數(shù)據(jù)槽

虛擬槽分布方式中惭适,由于每個節(jié)點管理一部分數(shù)據(jù)槽,數(shù)據(jù)保存到數(shù)據(jù)槽中楼镐。當節(jié)點擴容或者縮容時癞志,對數(shù)據(jù)槽進行重新分配遷移即可,數(shù)據(jù)不會丟失框产。

節(jié)點內(nèi)部通信機制

在分布式的存儲方式中凄杯,還有另外一個點需要我們關(guān)注,那就是集群之間的內(nèi)部通信方式秉宿,畢竟整個集群是需要知道當前集群中有多少有效的節(jié)點戒突,這些節(jié)點分配的 ip 以及一些其他的數(shù)據(jù),這些數(shù)據(jù)我們可以稱之為元數(shù)據(jù)描睦。

集群元數(shù)據(jù)的維護有兩種方式:集中式膊存、 Gossip 協(xié)議。而 Redis Cluster 節(jié)點間采用 Gossip 協(xié)議進行通信酌摇。

集中式是將集群元數(shù)據(jù)(節(jié)點信息膝舅、故障等等)幾種存儲在某個節(jié)點上。集中式元數(shù)據(jù)集中存儲的一個典型代表窑多,就是大數(shù)據(jù)領(lǐng)域的 storm 仍稀。它是分布式的大數(shù)據(jù)實時計算引擎,是集中式的元數(shù)據(jù)存儲的結(jié)構(gòu)埂息,底層基于 zookeeper (分布式協(xié)調(diào)的中間件)對所有元數(shù)據(jù)進行存儲維護技潘。

image

Redis 維護集群元數(shù)據(jù)采用另一個方式遥巴, Gossip 協(xié)議,所有節(jié)點都持有一份元數(shù)據(jù)享幽,不同的節(jié)點如果出現(xiàn)了元數(shù)據(jù)的變更铲掐,就不斷將元數(shù)據(jù)發(fā)送給其它的節(jié)點,讓其它節(jié)點也進行元數(shù)據(jù)的變更值桩。

image

Gossip 協(xié)議

Gossip 協(xié)議是一種非常有意思的協(xié)議摆霉,它的過程是由一個種子節(jié)點發(fā)起,它會隨機的選擇周圍幾個節(jié)點散播消息奔坟,收到消息的節(jié)點也會重復(fù)該過程携栋,直至最終網(wǎng)絡(luò)中所有的節(jié)點都收到了消息。

這個過程可能需要一定的時間咳秉,由于不能保證某個時刻所有節(jié)點都收到消息婉支,但是理論上最終所有節(jié)點都會收到消息,因此它是一個最終一致性協(xié)議澜建。

image

Gossip 協(xié)議的一些特性:

  • 擴展性:網(wǎng)絡(luò)可以允許節(jié)點的任意增加和減少向挖,新增加的節(jié)點的狀態(tài)最終會與其他節(jié)點一致。
  • 容錯:網(wǎng)絡(luò)中任何節(jié)點的宕機和重啟都不會影響 Gossip 消息的傳播炕舵,Gossip 協(xié)議具有天然的分布式系統(tǒng)容錯特性何之。
  • 去中心化: Gossip 協(xié)議不要求任何中心節(jié)點,所有節(jié)點都可以是對等的幕侠,任何一個節(jié)點無需知道整個網(wǎng)絡(luò)狀況帝美,只要網(wǎng)絡(luò)是連通的,任意一個節(jié)點就可以把消息散播到全網(wǎng)晤硕。
  • 一致性收斂: Gossip 協(xié)議中的消息會以一傳十、十傳百一樣的指數(shù)級速度在網(wǎng)絡(luò)中快速傳播庇忌,因此系統(tǒng)狀態(tài)的不一致可以在很快的時間內(nèi)收斂到一致舞箍。消息傳播速度達到了 logN。
  • 消息的延遲:由于 Gossip 協(xié)議中皆疹,節(jié)點只會隨機向少數(shù)幾個節(jié)點發(fā)送消息疏橄,消息最終是通過多個輪次的散播而到達全網(wǎng)的,因此使用 Gossip 協(xié)議會造成不可避免的消息延遲略就。不適合用在對實時性要求較高的場景下捎迫。
  • 消息冗余: Gossip 協(xié)議規(guī)定,節(jié)點會定期隨機選擇周圍節(jié)點發(fā)送消息表牢,而收到消息的節(jié)點也會重復(fù)該步驟窄绒,因此就不可避免的存在消息重復(fù)發(fā)送給同一節(jié)點的情況,造成了消息的冗余崔兴,同時也增加了收到消息的節(jié)點的處理壓力彰导。而且蛔翅,由于是定期發(fā)送,因此位谋,即使收到了消息的節(jié)點還會反復(fù)收到重復(fù)消息山析,加重了消息的冗余。

Gossip 協(xié)議包含多種消息掏父,包含 ping , pong , meet , fail 等等笋轨。

  • meet:某個節(jié)點發(fā)送 meet 給新加入的節(jié)點,讓新節(jié)點加入集群中赊淑,然后新節(jié)點就會開始與其它節(jié)點進行通信爵政。
  • ping:每個節(jié)點都會頻繁給其它節(jié)點發(fā)送 ping,其中包含自己的狀態(tài)還有自己維護的集群元數(shù)據(jù)膏燃,互相通過 ping 交換元數(shù)據(jù)茂卦。
  • pong:返回 ping 和 meeet,包含自己的狀態(tài)和其它信息组哩,也用于信息廣播和更新等龙。
  • fail:某個節(jié)點判斷另一個節(jié)點 fail 之后,就發(fā)送 fail 給其它節(jié)點伶贰,通知其它節(jié)點說蛛砰,某個節(jié)點宕機啦。

由于 Redis Cluster 節(jié)點之間會定期交換 Gossip 消息黍衙,以及做一些心跳檢測泥畅,對網(wǎng)絡(luò)帶寬的壓力還有比較大的,包括官方都直接建議 Redis Cluster 節(jié)點數(shù)量不要超過 1000 個琅翻,當集群中節(jié)點數(shù)量過多的時候位仁,會產(chǎn)生不容忽視的帶寬消耗。

高可用和主備切換

一說到集群就不得不提高可用和主備切換方椎,而Redis cluster 的高可用的原理聂抢,幾乎跟哨兵是類似的。

判斷宕機

首先第一步當然是判斷宕機棠众,這和哨兵模式非常的像琳疏,同樣是分成兩種類型,一種是主觀宕機 pfail 闸拿,另一種的客觀宕機 fail 空盼。

  • 主觀宕機:一個節(jié)點認為另外一個節(jié)點宕機,這是一種「偏見」新荤,并不代表整個集群的認知揽趾。
  1. 節(jié)點 1 定期發(fā)送 ping 消息給節(jié)點 2 。
  2. 如果發(fā)送成功迟隅,代表節(jié)點 2 正常運行但骨,節(jié)點 2 會響應(yīng) PONG 消息給節(jié)點 1 励七,節(jié)點 1 更新與節(jié)點 2 的最后通信時間
  3. 如果發(fā)送失敗,則節(jié)點 1 與節(jié)點 2 之間的通信異常判斷連接奔缠,在下一個定時任務(wù)周期時掠抬,仍然會與節(jié)點 2 發(fā)送 ping 消息
  4. 如果節(jié)點 1 發(fā)現(xiàn)與節(jié)點 2 最后通信時間超過 cluster-node-timeout ,則把節(jié)點 2 標識為 pfail 狀態(tài)校哎。
  • 客觀宕機:當半數(shù)以上持有槽的主節(jié)點都標記某節(jié)點主觀下線两波。
  1. 當節(jié)點 1 認為節(jié)點 2 宕機后,那么會在 Gossip ping 消息中闷哆, ping 給其他節(jié)點腰奋。
  2. 當其他節(jié)點會重新嘗試之前節(jié)點 1 主觀宕機的過程。
  3. 如果有超過半數(shù)的節(jié)點都認為 pfail 了抱怔,那么這個節(jié)點 2 就會變成真的 fail 劣坊。

注意:集群模式下,只有主節(jié)點( master )才有讀寫權(quán)限和集群槽的維護權(quán)限屈留,從節(jié)點( slave )只有復(fù)制的權(quán)限局冰。

從節(jié)點選舉

  1. 先檢查資格,檢查所有的 salve 與 master 斷開連接的時間灌危,如果超過了 cluster-node-timeout * cluster-slave-validity-factor 康二,那么久沒有資格成為 master 。
  2. 每個從節(jié)點勇蝙,都根據(jù)自己對 master 復(fù)制數(shù)據(jù)的 offset沫勿,來設(shè)置一個選舉時間,offset 越大(復(fù)制數(shù)據(jù)越多)的從節(jié)點味混,選舉時間越靠前产雹,優(yōu)先進行選舉。
  3. 所有的 master 開始選舉投票翁锡,如果大部分 master 節(jié)點 (N/2 + 1) 都投票給了某個從節(jié)點洽故,那么選舉通過,那個從節(jié)點可以切換成 master 盗誊。
  4. 從節(jié)點執(zhí)行主備切換,從節(jié)點切換為主節(jié)點隘弊。

參考

https://www.cnblogs.com/williamjie/p/11132211.html

https://github.com/doocs/advanced-java/blob/master/docs/high-concurrency/redis-cluster.md

https://zhuanlan.zhihu.com/p/41228196

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末哈踱,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子梨熙,更是在濱河造成了極大的恐慌开镣,老刑警劉巖,帶你破解...
    沈念sama閱讀 222,729評論 6 517
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件咽扇,死亡現(xiàn)場離奇詭異邪财,居然都是意外死亡陕壹,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,226評論 3 399
  • 文/潘曉璐 我一進店門树埠,熙熙樓的掌柜王于貴愁眉苦臉地迎上來糠馆,“玉大人,你說我怎么就攤上這事怎憋∮致担” “怎么了?”我有些...
    開封第一講書人閱讀 169,461評論 0 362
  • 文/不壞的土叔 我叫張陵绊袋,是天一觀的道長毕匀。 經(jīng)常有香客問我,道長癌别,這世上最難降的妖魔是什么皂岔? 我笑而不...
    開封第一講書人閱讀 60,135評論 1 300
  • 正文 為了忘掉前任,我火速辦了婚禮展姐,結(jié)果婚禮上躁垛,老公的妹妹穿的比我還像新娘。我一直安慰自己诞仓,他們只是感情好缤苫,可當我...
    茶點故事閱讀 69,130評論 6 398
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著墅拭,像睡著了一般活玲。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上谍婉,一...
    開封第一講書人閱讀 52,736評論 1 312
  • 那天舒憾,我揣著相機與錄音,去河邊找鬼穗熬。 笑死镀迂,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的唤蔗。 我是一名探鬼主播探遵,決...
    沈念sama閱讀 41,179評論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼妓柜!你這毒婦竟也來了箱季?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 40,124評論 0 277
  • 序言:老撾萬榮一對情侶失蹤棍掐,失蹤者是張志新(化名)和其女友劉穎藏雏,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體作煌,經(jīng)...
    沈念sama閱讀 46,657評論 1 320
  • 正文 獨居荒郊野嶺守林人離奇死亡掘殴,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,723評論 3 342
  • 正文 我和宋清朗相戀三年赚瘦,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片奏寨。...
    茶點故事閱讀 40,872評論 1 353
  • 序言:一個原本活蹦亂跳的男人離奇死亡起意,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出服爷,到底是詐尸還是另有隱情杜恰,我是刑警寧澤,帶...
    沈念sama閱讀 36,533評論 5 351
  • 正文 年R本政府宣布仍源,位于F島的核電站心褐,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏笼踩。R本人自食惡果不足惜逗爹,卻給世界環(huán)境...
    茶點故事閱讀 42,213評論 3 336
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望嚎于。 院中可真熱鬧掘而,春花似錦、人聲如沸于购。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,700評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽肋僧。三九已至斑胜,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間嫌吠,已是汗流浹背止潘。 一陣腳步聲響...
    開封第一講書人閱讀 33,819評論 1 274
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留辫诅,地道東北人凭戴。 一個月前我還...
    沈念sama閱讀 49,304評論 3 379
  • 正文 我出身青樓,卻偏偏與公主長得像炕矮,于是被迫代替她去往敵國和親么夫。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 45,876評論 2 361