Redis——Cluster

為什么需要集群?

  • 高并發(fā):
  • 大數(shù)據(jù):
  • 集群分區(qū)方式


    數(shù)據(jù)分區(qū)
    • 順序分區(qū)

    • 哈希分區(qū)

      • 節(jié)點(diǎn)取余分區(qū)

        • 客戶(hù)端分片:進(jìn)行哈希+取余


          節(jié)點(diǎn)取余
        • 擴(kuò)容:
          存在問(wèn)題:當(dāng)需要擴(kuò)充節(jié)點(diǎn)的時(shí)候,需要進(jìn)行大量的數(shù)據(jù)遷移(解決方案:翻倍擴(kuò)容,會(huì)降低數(shù)據(jù)的遷移量)
          圖片.png
      • 一致性哈希分區(qū)
        一致性哈希分區(qū)采用一致性哈希算法進(jìn)行分區(qū),由客戶(hù)端計(jì)算并且提供一致性hash,基本步驟如下;

        • 客戶(hù)端分片:進(jìn)行哈希+(順時(shí)針)優(yōu)化取余
        • 首先求出Redis服務(wù)器(節(jié)點(diǎn))的哈希值,并將其配置到0~2的32次方的圓(continuum)上。
        • 然后采用同樣的方法求出存儲(chǔ)數(shù)據(jù)的鍵的哈希值,并映射到相同的圓上。
        • 然后從數(shù)據(jù)映射到的位置開(kāi)始順時(shí)針查找,將數(shù)據(jù)保存到找到的第一個(gè)服務(wù)器上。如果超過(guò)2的32次方仍然找不到服務(wù)器,就會(huì)保存到第一臺(tái)Redis服務(wù)器上。


          一致性哈希算法
        • 擴(kuò)容
          只影響鄰近節(jié)點(diǎn),但是還是存在數(shù)據(jù)遷移,使用翻倍擴(kuò)容保證最小遷移數(shù)據(jù)和負(fù)載均衡
          圖片.png
    • 虛擬槽分區(qū)(Redis-Cluster采用)
      槽(slot):每個(gè)預(yù)設(shè)虛擬槽映射一個(gè)數(shù)據(jù)子集,一般比節(jié)點(diǎn)數(shù)大,Redis集群的整個(gè)數(shù)據(jù)庫(kù)被分成16384(0~16383)個(gè)槽,數(shù)據(jù)庫(kù)中的每個(gè)鍵都屬于這些槽中的一個(gè)。


      虛擬槽分區(qū)

      數(shù)據(jù)分布對(duì)比
Redis 集群:是一個(gè)通過(guò)分片(sharding)在多個(gè)Redis間節(jié)點(diǎn)間共享數(shù)據(jù)的分布式數(shù)據(jù)庫(kù)方案,提供復(fù)制和故障轉(zhuǎn)移功能。
  • 節(jié)點(diǎn)
    是組成Redis集群的基本元素,一個(gè)Redis集群包含多個(gè)節(jié)點(diǎn)。所有的主節(jié)點(diǎn)都負(fù)責(zé) 16384 個(gè)哈希槽中的一部分。當(dāng)集群處于穩(wěn)定狀態(tài)時(shí),集群中沒(méi)有在執(zhí)行重配置(reconfiguration)操作,每個(gè)哈希槽都只由一個(gè)節(jié)點(diǎn)進(jìn)行處理(不過(guò)主節(jié)點(diǎn)可以有一個(gè)或多個(gè)從節(jié)點(diǎn),可以在網(wǎng)絡(luò)斷線或節(jié)點(diǎn)失效時(shí)替換掉主節(jié)點(diǎn))。
    • 節(jié)點(diǎn)屬性:
      節(jié)點(diǎn)ID(唯一)是用于在整個(gè)集群中標(biāo)識(shí)每個(gè)節(jié)點(diǎn)。一個(gè)給定的節(jié)點(diǎn)可以在不改變節(jié)點(diǎn)ID的情況下改變 IP 和地址。集群能檢測(cè)到 IP 或端口的變化,然后使用在集群連接(cluster bus)上的 gossip 協(xié)議來(lái)發(fā)布廣播消息,通知配置變更。
      每個(gè)節(jié)點(diǎn)都有其他相關(guān)信息是所有節(jié)點(diǎn)都知道的:

      • 節(jié)點(diǎn)的 IP 地址和 TCP 端口號(hào)。
      • 各種標(biāo)識(shí)。
      • 節(jié)點(diǎn)使用的哈希槽。
      • 最近一次用集群連接發(fā)送 ping 包的時(shí)間。
      • 最近一次在回復(fù)中收到一個(gè) pong 包的時(shí)間。
      • 最近一次標(biāo)識(shí)節(jié)點(diǎn)失效的時(shí)間。
      • 該節(jié)點(diǎn)的從節(jié)點(diǎn)個(gè)數(shù)。
      • 如果該節(jié)點(diǎn)是從節(jié)點(diǎn),會(huì)有主節(jié)點(diǎn)ID信息。
    • 集群拓?fù)浣Y(jié)構(gòu)

      集群拓?fù)浣Y(jié)構(gòu)

      Redis 集群是一個(gè)網(wǎng)狀結(jié)構(gòu),每個(gè)節(jié)點(diǎn)都通過(guò) TCP 連接跟其他每個(gè)節(jié)點(diǎn)連接。在一個(gè)有 N 個(gè)節(jié)點(diǎn)的集群中,每個(gè)節(jié)點(diǎn)都有 N-1 個(gè)流出的 TCP 連接,和 N-1 個(gè)流入的連接。 這些 TCP 連接會(huì)永久保持,并不是按需創(chuàng)建的。

    • 節(jié)點(diǎn)握手
      只有在兩種方式下,一個(gè)節(jié)點(diǎn)才會(huì)認(rèn)為另一個(gè)節(jié)點(diǎn)是集群中的一部分:

      • 當(dāng)一個(gè)節(jié)點(diǎn)node發(fā)送CLUSTER MEET IP PORT命令,可以讓node節(jié)點(diǎn)與指定節(jié)點(diǎn)進(jìn)行握手,握手成功時(shí),node節(jié)點(diǎn)就會(huì)被指定節(jié)點(diǎn)添加到他當(dāng)前所在的集群中。
      • 一個(gè)已被信任的節(jié)點(diǎn)能通過(guò)傳播gossip消息讓另一個(gè)節(jié)點(diǎn)被注冊(cè)為集群中的一部分。也就是說(shuō),如果 A 知道 B,B 知道 C,那么 B 會(huì)向 A 發(fā)送 C 的gossip消息。A 收到后就會(huì)把 C 當(dāng)作是網(wǎng)絡(luò)中的一部分,并且嘗試連接 C。 這意味著,只要我們往任何連接圖中加入節(jié)點(diǎn),它們最終會(huì)自動(dòng)形成一個(gè)完全連接圖。從根本上來(lái)說(shuō),這表示集群能自動(dòng)發(fā)現(xiàn)其他節(jié)點(diǎn),但前提是有一個(gè)由系統(tǒng)管理員強(qiáng)制創(chuàng)建的信任關(guān)系(MEET)。 這個(gè)機(jī)制能防止不同的 Redis 集群因?yàn)?IP 地址變更或者其他網(wǎng)絡(luò)事件而意外混合起來(lái),從而使集群更具健壯性。 當(dāng)節(jié)點(diǎn)的網(wǎng)絡(luò)連接斷掉時(shí),它會(huì)積極嘗試連接所有其他已知節(jié)點(diǎn)。
        簡(jiǎn)單來(lái)說(shuō),
        1.Redis Cluster中的節(jié)點(diǎn)A發(fā)送MEET消息通知另外一個(gè)節(jié)點(diǎn)B,讓節(jié)點(diǎn)B把節(jié)點(diǎn)A當(dāng)做Cluster中的一員。
        2.如果節(jié)點(diǎn)A認(rèn)識(shí)節(jié)點(diǎn)B,節(jié)點(diǎn)B認(rèn)識(shí)節(jié)點(diǎn)C,那么節(jié)點(diǎn)B可以發(fā)送包含節(jié)點(diǎn)C信息的MEET消息給節(jié)點(diǎn)A,從而節(jié)點(diǎn)A也認(rèn)識(shí)節(jié)點(diǎn)C了,即節(jié)點(diǎn)A將與節(jié)點(diǎn)C建立連接。
  • 槽分配
    關(guān)于槽,上面已經(jīng)說(shuō)過(guò)了,假設(shè)我們現(xiàn)在使用cluster meet 搭建了一個(gè)三個(gè)節(jié)點(diǎn)的集群,但是呢,現(xiàn)在這個(gè)集群是處于下線狀態(tài)的,為什么呢?
    當(dāng)數(shù)據(jù)庫(kù)中的16384個(gè)槽都有節(jié)點(diǎn)在處理時(shí),集群是處于上線狀態(tài)的,相反的,只要有一個(gè)槽沒(méi)有得到處理,那么集群處于下線狀態(tài)。因?yàn)槲覀兗褐械娜齻€(gè)節(jié)點(diǎn)都沒(méi)有在處理任何槽,所以集群是下線狀態(tài)的。
  • 集群搭建(原生安裝)
    1. 配置開(kāi)啟節(jié)點(diǎn)
    2. 節(jié)點(diǎn)握手
    3. 分配槽
    4. 分配主從關(guān)系
      關(guān)于安裝配置的方法大家自己查詢(xún)即可,這里只是為了理解集群的架構(gòu),需要注意的是這種方法不太常用,還是推薦Redis官方的Ruby安裝(需要注意服務(wù)器綁定的地址,127.0.0.0會(huì)存在回環(huán)問(wèn)題,建議綁定外網(wǎng)地址)。
  • 集群伸縮
    集群伸縮實(shí)際上就是=槽和數(shù)據(jù)在節(jié)點(diǎn)之間的移動(dòng)
    伸縮原理
    • 集群擴(kuò)展過(guò)程
      • 準(zhǔn)備新節(jié)點(diǎn)
      • 加入集群
      • 遷移槽和數(shù)據(jù)
    • 集群收縮過(guò)程
      • 下線遷移槽(假設(shè)持有槽)
      • 通知其他節(jié)點(diǎn)忘記該節(jié)點(diǎn)
      • 關(guān)閉節(jié)點(diǎn)
  • 客戶(hù)端路由
    • moved重定向
      一個(gè) Redis 客戶(hù)端可以自由地向集群中的任意節(jié)點(diǎn)(包括從節(jié)點(diǎn))發(fā)送查詢(xún)。接收的節(jié)點(diǎn)會(huì)分析查詢(xún),如果這個(gè)命令是集群可以執(zhí)行的(就是查詢(xún)中只涉及一個(gè)鍵),那么節(jié)點(diǎn)會(huì)找這個(gè)鍵所屬的哈希槽對(duì)應(yīng)的節(jié)點(diǎn)。

如果剛好這個(gè)節(jié)點(diǎn)就是對(duì)應(yīng)這個(gè)哈希槽,那么這個(gè)查詢(xún)就直接被節(jié)點(diǎn)處理掉。否則這個(gè)節(jié)點(diǎn)會(huì)查看它內(nèi)部的 哈希槽 -> 節(jié)點(diǎn)ID 映射,然后給客戶(hù)端返回一個(gè) MOVED 錯(cuò)誤。


moved
  • ask重定向
    當(dāng)我們使用 MOVED 的時(shí)候,意味著我們認(rèn)為哈希槽永久地被另一個(gè)不同的節(jié)點(diǎn)處理,并且希望接下來(lái)的所有查詢(xún)都嘗試發(fā)到這個(gè)指定的節(jié)點(diǎn)上去。而 ASK 意味著我們只要下一個(gè)查詢(xún)發(fā)送到指定節(jié)點(diǎn)上去。
    圖片.png

    兩者都是客戶(hù)端重定向;
    moved:槽已經(jīng)確定遷移,以后對(duì)該槽的請(qǐng)求都發(fā)送到目標(biāo)節(jié)點(diǎn);
    ask:槽還在遷移當(dāng)中,只有這一次對(duì)該槽的請(qǐng)求都發(fā)送到目標(biāo)節(jié)點(diǎn),以后還是請(qǐng)求源節(jié)點(diǎn);
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容