Redis學習筆記(十八) 集群(下)

来源:https://www.cnblogs.com/xtt321/archive/2020/06/10/13089753.html
-Advertisement-
Play Games

複製和故障轉移 Redis集群中的節點分為主節點(master)和從節點(slave),其中主節點用於處理槽,而從節點則用於複製某個主節點,併在被覆制 的主節點下線時,代替下線主節點繼續處理命令請求。 設置從節點:CLUSTER REPLICATE < node_id >可以讓接收命令的節點稱為no ...


複製和故障轉移

Redis集群中的節點分為主節點(master)和從節點(slave),其中主節點用於處理槽,而從節點則用於複製某個主節點,併在被覆制 的主節點下線時,代替下線主節點繼續處理命令請求。

設置從節點:CLUSTER REPLICATE < node_id >可以讓接收命令的節點稱為node_id 所指定節點的從節點,並開始對主節點進行複製。

1)接收到該命令的節點首先會在自己的clusterState.nodes字典中找到node_id所對應節點的clusterNode結構,並將自己的clusterState.myself.slaveof指針指向這個結構,以此來記錄這個節點正在複製的主節點:

struct clusterNode{
    //如果這個時一個從節點,那麼指向主節點
    struct clusterNode *slaveof;
}

2)節點修改自己的clusterState.myself.flags中的屬性,關閉原本的REDIS_NODE_MASTER標識,打開REDIS_NODE_SLAVE標識,標識這個節點已經由原來的主節點變成了從節點。

3)節點會調用複製代碼,根據clusterState.myself.slaveof指向clusterNode結構所保存的IP地址和埠號,對節點進行複製。

一個節點稱為從節點,並開始複製某個主節點這一信息會通過消息發送給集群中的其他節點,最終集群中的所有節點都會知道某個從節點正在複製某個主節點。

集群中的所有節點都會在代表主節點的clusterNode結構的slaves屬性和numslaves屬性中記錄正在複製這個主節點的從節點名單:

struct clusterNode{
    //正在複製這個主節點的從節點數量
    int numslaves;
    //數組,每個數組項指向一個正在複製這個主節點的從節點的clusterNode
    struct clusterNode **slaves;
}

集群中的每個節點都會定期地向集群中的其他節點發送PING消息,一次來檢測對方是否線上,如果接收PING消息的節點沒有在規定的時間內,向發送PING消息的節點返回PONG消息,那麼發送PING消息的節點就會將階段後PING消息的節點標記為疑似下線(PFAIL)。

集群中的各個節點會通過相互發送消息的方式來交換集群中各個節點的狀態信息:某個節點處於線上狀態、疑似下線、已下線狀態。

當一個主節點A通過罅隙得知主節點B認為主節點C進入疑似下線狀態時,主節點A會在自己的clusterState.nodes字典中找到主節點C所對應的clusterNode結構,並將主節點B的下線報告添加到clusterNode結構的fail_reports鏈表中

status clusterNode{
    list *fali_reports;//鏈表,記錄所有其他節點對該節點的下線報告
};

下線報告結構:

 

struct c;isterNodeFailReport{
    //報告目標節點已經下線的節點
    struct clusterNode *node;
    //最後一個從node節點收到下線報告的時間(程式使用這個時間戳來檢查下線報告是否過期)
    mstime_t time;
} typedef clusterNodeFailReport;

如果集群里半數以上負責處理槽的主節點都將某個主節點x報告未疑似下線,那麼這個主節點x將被標記未已下線,將主節點x標記為已下線的節點會向集群廣播一條關於主節點x的FAIL罅隙,所有收到這條罅隙的節點都會立即將主節點x標記為已下線。

故障轉移的步驟:

1)複製下線主節點的所有從節點裡面,會有一個從節點被選中,

2)被選中的從節點會執行SLAVEOF no one命令,成為新的主節點。

3)新的主節點會撤銷所有對已下線主節點的槽指派,並將這些槽指派給自己。

4)新的主節點向集群廣播一條PONG消息,這條消息讓其他集群中的其他節點立即知道這個節點已經由從節點變為主節點,並且這個主節點已經接管了原本已下線節點負責處理的槽。

5)新的主節點開始接收和自己負責處理的槽有關的命令請求,故障轉移完成。

選舉新的主節點:

1)集群的配置紀元是一個計數器。他的初始值為0;

2)當集群中的某個節點開始一次故障轉移操作時,集群配置紀元的值會被加1。

3)集群裡面每個負責處理槽的主節點都有一次投票機會,而第一個向主節點要求投票的從節點將獲得主節點的投票。

4)當從節點發現自己正在複製的主節點進入下線狀態時,從節點會向集群官博一條CLUSTERMSG_TYPE_FAILOVER_AUTH_REQUEST消息,要求所有收到這個消息、並且具有投票權的主節點向這個從節點投票。

5)如果一個主節點具有投票權,並且這個主節點尚未投票給其他從節點,那麼主節點將向要求投票的從節點返回一條CLUSTERMSG_TYPE_FAILOVER_AUTH_ACK消息,表示這個主節點支持從節點成為新的主節點。

6)每個參與選舉的從節點都會收到CLUSTERMSG_TYPE_FAILOVER_AUTH_ACK消息,並根據自己收到了多少條這種消息來統計自己獲得了多少主節點支持。

7)如果集群中有N個具有投票權的主節點,那麼當一個從節點大於等於N/2+1張支持票時,這個從節點就當選成為新的主節點。

8)如果在一個配置紀元裡面沒有從節點收集到足夠多的支持票,那麼集群進入下一個紀元,再次進行選舉,直到選出新的主節點為止。

 

消息

集群中各個節點通過發送和接收消息來進行通信,我們稱發送消息的節點為發送者,接收消息的節點為接收者:

1)MEET消息,當發送者接到客戶端發送的CLUSTER MEET命令時,發送者會向接收者發送MEET消息,請求接收者加入到發送者當前所處的集群裡面。

2)PING消息,集群裡面的每個節點預設每隔一秒鐘就會從已知節點列表中隨機選出五個節點,然後對這五個節點中最長時間沒有發送過PING消息的節點發送PING消息,以此檢測被選中的節點是否線上。除此之外,如果節點A最後一次收到節點B發送的PONG消息的時間,距離當前時間已超過了節點A的cluster-node-timeout選項設置時長的一半,那麼節點A也會向節點B發送PING消息,這可以防止節點A因長時間沒有隨機選中節點B作為PING消息的發送對象而導致節點B的信息更新滯後。

3)PONG消息,當接收者收到發送者發來的MEET消息或者PING時,為了向發送者確認這條MEET、PING消息已到達,接收者會向發送者返回一條PONG消息。另外,一個節點也可以通過向集群發送集群廣播自己的PONG消息來讓集群中的其他節點立即刷新關於這個節點的認識。

4)FAIL消息,當一個主節點A判斷另一個主節點B已經進入FAIL狀態時,節點A會會向集群廣播一條關於節點B的FAIL消息,所有接收到這條消息的節點都會立即將節點B標記為已下線。

5)PUBLISH消息,當節點接收到一個PUBLISH命令時,節點會執行這個命令,並向集群廣播一條PUBLISH消息,所有接收到這條PUBLISH消息的節點都會執行相同的PUBLISH命令。

一條消息由消息頭(header)和消息正文(data組成)

消息頭:

typedef struct {
    //消息的長度(消息頭的長度和消息正文的長度)
    uint32_t totlen;
    //消息的類型
    uint16_t type;
    //消息正文包含的節點信息數量
    //只有發送MEET、PING、PONG這三種Gossip協議消息時使用
    uint16_t count;
    
    //薩松這所處的配置紀元
    uint64_t currentEpoch;
    //如果發送者是一個主節點,那麼這裡面記錄的時發送者的配置紀元
    //如果發送者時一個從節點,那麼這裡面記錄的時發送者正在複製的主節點的配置紀元
    uint64_t configEpoch;
    //發送者的名稱(ID)
    char sender[REDIS_CLUSTER_NAMELEN];
    //發送者目前的槽指派信息
    unsigned char myslots[REDIS_CLUSTER_SLOTS/8];
    //如果發送者是一個從節點,記錄的是發送者正在複製的主節點的名稱
    //如果發送者是一個主節點,那麼這裡記錄的是REDIS_NODE_NULL_NAME
    char slaveof[REDIS_CLUSTER_NAMELEN];
    //發送者的埠號
    uint16_t port;
    //發送者的標識值
    uint16_t flags;
    //發送者所處集群的狀態
    unsigned char state;
    //消息正文
    union clusterMsgData data;
} clusterMsg;

clusterMsg.data 結構:

union clusterMsgData{
    //MEET PING PONG 消息正文
    struct{
        //每條MEET PING PONG消息都包含兩個 clusterMsgDataGossip 結構
        clusterMsgDataGossip gossip[1]
    } ping;
    //FAIL 消息正文
    struct{
        clusterMsgDataFail about;
    } fali;
    
    //PUBLISH消息正文
    struct{
        clusterMsgDataPublish msg;
    } publish;
}

clusterMsgDataGossip結構記錄了選中節點的名字,發送者與被選中節點最後一次發送和接收PING消息和PONG消息的時間戳,被選中節點的IP地址和埠號,以及被選中節點的標識值:

typedef struct {
    //節點的名字
    char nodename[REDIS_CLUSTER_NAMELEN];
    //最後一次向該節點發送PING消息的時間戳
    uint32_t ping_sent;
    //最後一次從該 節點接收到PONG消息的時間戳
    uint32_t pong_received;
    //節點的IP地址
    char ip[16];
    //節點的埠號
    uint16_t port;
    //節點的標識值
    uint16_t flags;
} clusterMsgDataGossip;

每天學一點,總會有收穫。

 

說明:尊重作者知識產權,文中內容參考《Redis設計與實現》,僅在此做學習與大家分享。

 


 

 


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 概述 Zabbix 5.0已經正式發佈,相比4.0,它在可用性,安全性和完整性方面都有一系列重要改進。 支持的平臺 除了現有的官方軟體包和appliances外,Zabbix 5.0現在還支持以下平臺: SUSE Linux Enterprise Server 15 Debian 10 Ubuntu ...
  • 1、Linux環境下安裝jdk (1)在官網下載一個jdk的版本: https://www.oracle.com/technetwork/cn/java/javase/downloads/index.html 點擊勾選後,直接下載 (2)下載tar包之後,直接解壓jdk:tar -zxf jdk-1 ...
  • MCU是智能控制的主要核心,是目前物聯網和汽車電子未來主要增長點。MCU微控制器作為智能控制的核心廣泛應用於消費電子、汽車電子、電腦與網路、工業控制等領域,伴隨物聯網的逐步落地和汽車電子的發展,MCU微控制器的市場需求增長顯著。 國內MCU微控制器市場未來五年複合增速達11.7%,至2020年市場 ...
  • awk是一個強大的文本分析工具,是把文件逐行的讀入,以空格為預設分隔符將每行切片,切開的部分再進行各種分析處理。 awk其名稱得自於它的創始人 Alfred Aho 、Peter Weinberger 和 Brian Kernighan 姓氏的首字母。實際上 AWK 的確擁有自己的語言: AWK程式 ...
  • 我無意引起單片機、Linux、Android孰優孰劣的討論,我確實不看好純粹的單片機軟體開發,但是很看好RTOS及物聯網在單片機上的應用。 生活不容易,碼農不容易,走上碼農之路,只有不斷學習了。 ...
  • 實現raid有2種方式:軟體 RAID 的性能較低,因為其使用主機的資源。 需要載入 RAID 軟體以從軟體 RAID 捲中讀取數據。在載入 RAID 軟體前,操作系統需要引導起來才能載入 RAID 軟體。在軟體 RAID 中無需物理硬體。零成本投資。硬體 RAID 的性能較高。他們採用 PCI E... ...
  • 一、檢查 Linux 上是有存在 docker [root@localhost bin]# docker version 不存在 docker 時,可以使用如下命令下載 docker [root@localhost local]# yum -y install docker 在使用 docker 版 ...
  • 所有知識體系文章,GitHub已收錄,歡迎Star!再次感謝,願你早日進入大廠! GitHub地址: https://github.com/Ziphtracks/JavaLearningmanual MySQL存儲過程 一、存儲過程 1.1 什麼是存儲過程 存儲過程(Stored Procedure ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...