日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 运维知识 > 数据库 >内容正文

数据库

Redis:redis cluster的实现细节

發(fā)布時(shí)間:2025/3/21 数据库 38 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Redis:redis cluster的实现细节 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

本片博文主要介紹:

rediscluster 主要實(shí)現(xiàn)的是 數(shù)據(jù)分片到每一個(gè)節(jié)點(diǎn),各節(jié)點(diǎn)之間如何通訊并保持?jǐn)?shù)據(jù)的一致性、節(jié)點(diǎn)狀態(tài)的同步性!如何即時(shí)刷新整個(gè)集群系統(tǒng)的狀態(tài)更新。

1)數(shù)據(jù)分片

??? 16384個(gè)slot

2)客戶端對(duì)每個(gè)節(jié)點(diǎn)請(qǐng)求的時(shí)候,如果是服務(wù)器端分片策略,那么當(dāng)客戶端請(qǐng)求過來,會(huì)出現(xiàn)重定向的過程。

???? 服務(wù)器計(jì)算出正確的節(jié)點(diǎn),并回送地址。

???? MOVE

???? ASK

3)數(shù)據(jù)同步

??? 心跳機(jī)制 ======》? header (自己的信息) + gossip(自己所知的其他節(jié)點(diǎn)的信息)?

4)故障恢復(fù)

??? master宕機(jī),slave轉(zhuǎn)主。獲取版本號(hào)。發(fā)送投票請(qǐng)求,獲取請(qǐng)求回復(fù),票數(shù)過半,轉(zhuǎn)主,發(fā)送廣播消息同步各節(jié)點(diǎn)信息。

Redis Cluster 實(shí)現(xiàn)

本文將從設(shè)計(jì)思路,功能實(shí)現(xiàn)幾個(gè)方面介紹Redis Cluster。(下面提到的epoch(類似于Raft算法“term”(任期)

假設(shè)讀者已經(jīng)了解Redis Cluster的使用方式,不了解可以先看之前一篇介紹Redis Cluster的博客。

簡(jiǎn)介

Redis Cluster作為Redis的分布式實(shí)現(xiàn),主要做了兩個(gè)方面的事情:

1,數(shù)據(jù)分片

  • Redis Cluster將數(shù)據(jù)按key哈希到16384個(gè)slot上
  • Cluster中的不同節(jié)點(diǎn)負(fù)責(zé)一部分slot

2,故障恢復(fù)

  • Cluster中直接提供服務(wù)的節(jié)點(diǎn)為Master
  • 每個(gè)Master可以有一個(gè)或多個(gè)Slave
  • 當(dāng)Master不能提供服務(wù)時(shí),Slave會(huì)自動(dòng)Failover

設(shè)計(jì)思路

性能為第一目標(biāo)

  • 每一次數(shù)據(jù)處理都是由負(fù)責(zé)當(dāng)前slot的Master直接處理的,沒有額外的網(wǎng)絡(luò)開銷

提高可用性

  • 水平擴(kuò)展能力 :由于slot的存在,增加機(jī)器節(jié)點(diǎn)時(shí)只需要將之前由其他節(jié)點(diǎn)處理的一部分slot重新分配給新增節(jié)點(diǎn)。slot可以看做機(jī)器節(jié)點(diǎn)和用戶數(shù)據(jù)之間的一個(gè)抽象層。
  • 故障恢復(fù):Slave會(huì)在需要的時(shí)候自動(dòng)提升為Master

損失一致性

  • Master與Slave之間異步復(fù)制即Master先向用戶返回結(jié)果后再異步將數(shù)據(jù)同步給Slave,這就導(dǎo)致Master宕機(jī)后一部分已經(jīng)返回用戶的數(shù)據(jù)在新Master上不存在
  • 網(wǎng)絡(luò)分區(qū)時(shí),由于開始Failover前的超時(shí)時(shí)間,會(huì)有一部分?jǐn)?shù)據(jù)繼續(xù)寫到馬上要失效的Master上

功能實(shí)現(xiàn)

1,數(shù)據(jù)分片

我們已經(jīng)知道數(shù)據(jù)會(huì)按照key哈希到不同的slot,而每個(gè)節(jié)點(diǎn)僅負(fù)責(zé)一部分的slot,客戶端根據(jù)slot將請(qǐng)求交給不同的節(jié)點(diǎn)。將slots劃分給不同節(jié)點(diǎn)的過程稱為數(shù)據(jù)分片,對(duì)應(yīng)的還可以進(jìn)行分片的重新分配。這部分功能依賴外部調(diào)用命令:

分片

  • 對(duì)每個(gè)集群執(zhí)行CLUSTER ADDSLOTS slot [slot ...]
  • RedisCluster將命令指定的slots作為自己負(fù)責(zé)的部分

再分配

再分配要做的是將一些slots從當(dāng)前節(jié)點(diǎn)(source)遷移到其他節(jié)點(diǎn)(target)

  • 對(duì)target執(zhí)行CLUSTER SETSLOT slot IMPORTING [node-id],target節(jié)點(diǎn)將對(duì)應(yīng)slots記為importing狀態(tài);
  • 對(duì)source執(zhí)行CLUSTER SETSLOT MIGRATING[node-id],source節(jié)點(diǎn)將對(duì)應(yīng)slots記為migrating狀態(tài),與importing狀態(tài)一同在之后的請(qǐng)求重定向中使用
  • 獲取所有要遷移slot對(duì)應(yīng)的keys,CLUSTER GETKEYSINSLOT slot count
  • 對(duì)source?執(zhí)行MIGRATE host port key db timeout REPLACE [KEYS key [key ...]]
  • MIGRATE命令會(huì)將所有的指定的key通過RESTORE key ttl serialized-value REPLACE遷移給target
  • 對(duì)所有節(jié)點(diǎn)執(zhí)行CLUSTER SETSLOT slot NODE [node-id],申明target對(duì)這些slots的負(fù)責(zé),并退出importing或migrating

2,請(qǐng)求重定向(服務(wù)器端分片策略,客戶端和任意的服務(wù)器節(jié)點(diǎn)進(jìn)行連接)

由于每個(gè)節(jié)點(diǎn)只負(fù)責(zé)部分slot,以及slot可能從一個(gè)節(jié)點(diǎn)遷移到另一節(jié)點(diǎn),造成客戶端有可能會(huì)向錯(cuò)誤的節(jié)點(diǎn)發(fā)起請(qǐng)求。因此需要有一種機(jī)制來對(duì)其進(jìn)行發(fā)現(xiàn)和修正,這就是請(qǐng)求重定向。有兩種不同的重定向場(chǎng)景:

1),MOVE

  • ‘我’并不負(fù)責(zé)‘你’要的key,告訴’你‘正確的吧。
  • 返回CLUSTER_REDIR_MOVED錯(cuò)誤,和正確的節(jié)點(diǎn)。
  • 客戶端向該節(jié)點(diǎn)重新發(fā)起請(qǐng)求,注意這次依然又發(fā)生重定向的可能。

2),ASK

  • ‘我’負(fù)責(zé)請(qǐng)求的key,但不巧的這個(gè)key當(dāng)前在migraging狀態(tài),且‘我’這里已經(jīng)取不到了。告訴‘你’importing他的‘家伙’吧,去碰碰運(yùn)氣。
  • 返回CLUSTER_REDIR_ASK,和importing該key的節(jié)點(diǎn)。
  • 客戶端向新節(jié)點(diǎn)發(fā)送ASKING,之后再次發(fā)起請(qǐng)求
  • 新節(jié)點(diǎn)對(duì)發(fā)送過ASKING,且key已經(jīng)migrate過來的請(qǐng)求進(jìn)行響應(yīng)

3),區(qū)別

區(qū)分這兩種重定向的場(chǎng)景是非常有必要的:

  • MOVE,申明的是slot所有權(quán)的轉(zhuǎn)移,收到的客戶端需要更新其key-node映射關(guān)系
  • ASK,申明的是一種臨時(shí)的狀態(tài),所有權(quán)還并沒有轉(zhuǎn)移,客戶端并不更新其映射關(guān)系。前面的加的ASKING命令也是申明其理解當(dāng)前的這種臨時(shí)狀態(tài)

3,狀態(tài)檢測(cè)及維護(hù)

Cluster中的每個(gè)節(jié)點(diǎn)都維護(hù)一份在自己看來當(dāng)前整個(gè)集群的狀態(tài),主要包括:

  • 當(dāng)前集群狀態(tài)
  • 集群中各節(jié)點(diǎn)所負(fù)責(zé)的slots信息,及其migrate狀態(tài)
  • 集群中各節(jié)點(diǎn)的master-slave狀態(tài)
  • 集群中各節(jié)點(diǎn)的存活狀態(tài)及不可達(dá)投票

當(dāng)集群狀態(tài)變化時(shí),如新節(jié)點(diǎn)加入、slot遷移、節(jié)點(diǎn)宕機(jī)、slave提升為新Master,我們希望這些變化盡快的被發(fā)現(xiàn),傳播到整個(gè)集群的所有節(jié)點(diǎn)并達(dá)成一致。

節(jié)點(diǎn)之間相互的心跳(PING,PONG,MEET)及其攜帶的數(shù)據(jù)是集群狀態(tài)傳播最主要的途徑。

心跳時(shí)機(jī):

Redis節(jié)點(diǎn)會(huì)記錄其向每一個(gè)節(jié)點(diǎn)上一次發(fā)出ping和收到pong的時(shí)間,心跳發(fā)送時(shí)機(jī)與這兩個(gè)值有關(guān)。通過下面的方式既能保證及時(shí)更新集群狀態(tài),又不至于使心跳數(shù)過多:

  • 每次Cron向所有未建立鏈接的節(jié)點(diǎn)發(fā)送ping或meet
  • 每1秒從所有已知節(jié)點(diǎn)中隨機(jī)選取5個(gè),向其中上次收到pong最久遠(yuǎn)的一個(gè)發(fā)送ping
  • 每次Cron向收到pong超過timeout/2的節(jié)點(diǎn)發(fā)送ping
  • 收到ping或meet,立即回復(fù)pong

心跳數(shù)據(jù)

  • Header,發(fā)送者自己的信息
    • 所負(fù)責(zé)slots的信息
    • 主從信息
    • ip port信息
    • 狀態(tài)信息
  • Gossip,發(fā)送者所了解的部分其他節(jié)點(diǎn)的信息
    • ping_sent, pong_received
    • ip, port信息
    • 狀態(tài)信息,比如發(fā)送者認(rèn)為該節(jié)點(diǎn)已經(jīng)不可達(dá),會(huì)在狀態(tài)信息中標(biāo)記其為PFAIL或FAIL

心跳處理

  • 1,新節(jié)點(diǎn)加入
    • 發(fā)送meet包加入集群
    • 從pong包中的gossip得到未知的其他節(jié)點(diǎn)
    • 循環(huán)上述過程,直到最終加入集群
      • 2,Slots信息
        • 判斷發(fā)送者聲明的slots信息,跟本地記錄的是否有不同
        • 如果不同,且發(fā)送者epoch較大,更新本地記錄
        • 如果不同,且發(fā)送者epoch小,發(fā)送Update信息通知發(fā)送者
      • 3,Master slave信息
        • 發(fā)現(xiàn)發(fā)送者的master、slave信息變化,更新本地狀態(tài)
      • 4,節(jié)點(diǎn)Fail探測(cè)
        • 超過超時(shí)時(shí)間仍然沒有收到pong包的節(jié)點(diǎn)會(huì)被當(dāng)前節(jié)點(diǎn)標(biāo)記為PFAIL
        • PFAIL標(biāo)記會(huì)隨著gossip傳播
        • 每次收到心跳包會(huì)檢測(cè)其中對(duì)其他節(jié)點(diǎn)的PFAIL標(biāo)記
        • 對(duì)某個(gè)節(jié)點(diǎn)的PFAIL標(biāo)記達(dá)到大多數(shù)時(shí),將其變?yōu)镕AIL標(biāo)記并廣播FAIL消息

      注:Gossip的存在使得集群狀態(tài)的改變可以更快的達(dá)到整個(gè)集群。每個(gè)心跳包中會(huì)包含多個(gè)Gossip包,那么多少個(gè)才是合適的呢,redis的選擇是N/10,其中N是節(jié)點(diǎn)數(shù),這樣可以保證在PFAIL投票的過期時(shí)間內(nèi),節(jié)點(diǎn)可以收到80%機(jī)器關(guān)于失敗節(jié)點(diǎn)的gossip,從而使其順利進(jìn)入FAIL狀態(tài)

      廣播

      當(dāng)需要發(fā)布一些非常重要需要立即送達(dá)的信息時(shí),上述心跳加Gossip的方式就顯得捉襟見肘了,這時(shí)就需要向所有集群內(nèi)機(jī)器的廣播信息,使用廣播發(fā)的場(chǎng)景:

      • 節(jié)點(diǎn)的Fail信息:當(dāng)發(fā)現(xiàn)某一節(jié)點(diǎn)不可達(dá)時(shí),探測(cè)節(jié)點(diǎn)會(huì)將其標(biāo)記為PFAIL狀態(tài),并通過心跳傳播出去。當(dāng)某一節(jié)點(diǎn)發(fā)現(xiàn)這個(gè)節(jié)點(diǎn)的PFAIL超過半數(shù)時(shí)修改其為FAIL并發(fā)起廣播。
      • Failover Request信息:slave嘗試發(fā)起FailOver時(shí)廣播其要求投票的信息
      • 新Master信息:Failover成功的節(jié)點(diǎn)向整個(gè)集群廣播自己的信息

      4,故障恢復(fù)(Failover)

      當(dāng)slave發(fā)現(xiàn)自己的master變?yōu)镕AIL狀態(tài)時(shí),便嘗試進(jìn)行Failover,以期成為新的master。由于掛掉的master可能會(huì)有多個(gè)slave。Failover的過程需要經(jīng)過類Raft協(xié)議的過程在整個(gè)集群內(nèi)達(dá)到一致,其過程如下:

      • slave發(fā)現(xiàn)自己的master變?yōu)镕AIL
      • 將自己記錄的集群currentEpoch加1,并廣播Failover Request信息
      • 其他節(jié)點(diǎn)收到該信息,只有master響應(yīng),判斷請(qǐng)求者的合法性,并發(fā)送FAILOVER_AUTH_ACK,對(duì)每一個(gè)epoch只發(fā)送一次ack
      • 嘗試failover的slave收集FAILOVER_AUTH_ACK
      • 超過半數(shù)后變成新Master
      • 廣播Pong通知其他集群節(jié)點(diǎn)

?

《新程序員》:云原生和全面數(shù)字化實(shí)踐50位技術(shù)專家共同創(chuàng)作,文字、視頻、音頻交互閱讀

總結(jié)

以上是生活随笔為你收集整理的Redis:redis cluster的实现细节的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。