亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

Redis集群節(jié)點通信過程/原理流程分析

 更新時間:2022年03月18日 11:35:35   作者:IT利刃出鞘  
這篇文章主要介紹了Redis集群節(jié)點通信過程/原理,詳細介紹了Cluster(集群)的節(jié)點通信的流程,本文給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下

簡介

        本文介紹Redis的Cluster(集群)的節(jié)點通信的流程。

通信流程

        在分布式存儲中需要提供維護節(jié)點元數(shù)據(jù)信息的機制, 所謂元數(shù)據(jù)是指: 節(jié)點負責哪些數(shù)據(jù), 是否出現(xiàn)故障等狀態(tài)信息。 常見的元數(shù)據(jù)維護方式分為: 集中式和P2P方式。 Redis集群采用P2P的Gossip(流言) 協(xié)議,Gossip協(xié)議工作原理就是節(jié)點彼此不斷通信交換信息, 一段時間后所有的節(jié)點都會知道集群完整的信息, 這種方式類似流言傳播, 如下所示

通信過程說明:

  • 集群中的每個節(jié)點都會單獨開辟一個TCP通道, 用于節(jié)點之間彼此通信, 通信端口號在基礎端口上加10000。
  • 每個節(jié)點在固定周期內(nèi)通過特定規(guī)則選擇幾個節(jié)點發(fā)送ping消息。接收到ping消息的節(jié)點用pong消息作為響應。
  • 集群中每個節(jié)點通過一定規(guī)則挑選要通信的節(jié)點, 每個節(jié)點可能知道全部節(jié)點, 也可能僅知道部分節(jié)點, 只要這些節(jié)點彼此可以正常通信, 最終它們會達到一致的狀態(tài)。 當節(jié)點出故障、 新節(jié)點加入、 主從角色變化、 槽信息變更等事件發(fā)生時, 通過不斷的ping/pong消息通信, 經(jīng)過一段時間后所有的節(jié)點都會知道整個集群全部節(jié)點的最新狀態(tài), 從而達到集群狀態(tài)同步的目的。 

Gossip消息

消息流程

        Gossip協(xié)議的主要職責就是信息交換。 信息交換的載體就是節(jié)點彼此發(fā)送的Gossip消息, 了解這些消息有助于我們理解集群如何完成信息交換。

        常用的Gossip消息可分為: ping消息、 pong消息、 meet消息、 fail消息等, 它們的通信模式如下圖所示:

  • meet消息: 用于通知新節(jié)點加入。

消息發(fā)送者通知接收者加入到當前集群, meet消息通信正常完成后, 接收節(jié)點會加入到集群中并進行周期性的ping、 pong消息交換。

  • ping消息: 集群內(nèi)交換最頻繁的消息

 集群內(nèi)每個節(jié)點每秒向多個其他節(jié)點發(fā)送ping消息, 用于檢測節(jié)點是否在線和交換彼此狀態(tài)信息。 ping消息發(fā)送封裝了自身節(jié)點和部分其他節(jié)點的狀態(tài)數(shù)據(jù)。

  • pong消息: 當接收到ping、 meet消息時, 作為響應消息回復給發(fā)送方確認消息正常通信。

pong消息內(nèi)部封裝了自身狀態(tài)數(shù)據(jù)。 節(jié)點也可以向集群內(nèi)廣播自身的pong消息來通知整個集群對自身狀態(tài)進行更新。
fail消息: 當節(jié)點判定集群內(nèi)另一個節(jié)點下線時, 會向集群內(nèi)廣播一個fail消息, 其他節(jié)點接收到fail消息之后把對應節(jié)點更新為下線狀態(tài)。 具體細節(jié)將在后面“故障轉移”中說明。

消息格式

        所有的消息格式劃分為: 消息頭和消息體。 消息頭包含發(fā)送節(jié)點自身狀態(tài)數(shù)據(jù), 接收節(jié)點根據(jù)消息頭就可以獲取到發(fā)送節(jié)點的相關數(shù)據(jù), 結構如下:

typedef struct {
    char sig[4]; /* 信號標示 */
    uint32_t totlen; /* 消息總長度 */
    uint16_t ver; /* 協(xié)議版本*/
    uint16_t type; /* 消息類型,用于區(qū)分meet,ping,pong等消息 */
    uint16_t count; /* 消息體包含的節(jié)點數(shù)量, 僅用于meet,ping,ping消息類型*/
    uint64_t currentEpoch; /* 當前發(fā)送節(jié)點的配置紀元 */
    uint64_t configEpoch; /* 主節(jié)點/從節(jié)點的主節(jié)點配置紀元 */
    uint64_t offset; /* 復制偏移量 */
    char sender[CLUSTER_NAMELEN]; /* 發(fā)送節(jié)點的nodeId */
    unsigned char myslots[CLUSTER_SLOTS/8]; /* 發(fā)送節(jié)點負責的槽信息 */
    char slaveof[CLUSTER_NAMELEN]; /* 如果發(fā)送節(jié)點是從節(jié)點, 記錄對應主節(jié)點的nodeId */
    uint16_t port; /* 端口號 */
    uint16_t flags; /* 發(fā)送節(jié)點標識,區(qū)分主從角色, 是否下線等 */
    unsigned char state; /* 發(fā)送節(jié)點所處的集群狀態(tài) */
    unsigned char mflags[3]; /* 消息標識 */
    union clusterMsgData data /* 消息正文 */;
} clusterMsg;

        集群內(nèi)所有的消息都采用相同的消息頭結構clusterMsg, 它包含了發(fā)送節(jié)點關鍵信息, 如節(jié)點id、 槽映射、 節(jié)點標識(主從角色, 是否下線) 等。消息體在Redis內(nèi)部采用clusterMsgData結構聲明, 結構如下:

union clusterMsgData {
    /* ping,meet,pong消息體*/
    struct {
        /* gossip消息結構數(shù)組 */
        clusterMsgDataGossip gossip[1];
    } ping;
    
    /* FAIL 消息體 */
    struct {
        clusterMsgDataFail about;
    } fail;
    // ...
};

        消息體clusterMsgData定義發(fā)送消息的數(shù)據(jù), 其中ping、 meet、 pong都采用cluster MsgDataGossip數(shù)組作為消息體數(shù)據(jù), 實際消息類型使用消息頭的type屬性區(qū)分。 每個消息體包含該節(jié)點的多個clusterMsgDataGossip結構數(shù)據(jù), 用于信息交換, 結構如下:

typedef struct {
    char nodename[CLUSTER_NAMELEN]; /* 節(jié)點的nodeId */
    uint32_t ping_sent; /* 最后一次向該節(jié)點發(fā)送ping消息時間 */
    uint32_t pong_received; /* 最后一次接收該節(jié)點pong消息時間 */
    char ip[NET_IP_STR_LEN]; /* IP */
    uint16_t port; /* port*/
    uint16_t flags; /* 該節(jié)點標識, */
} clusterMsgDataGossip;

        當接收到ping、 meet消息時, 接收節(jié)點會解析消息內(nèi)容并根據(jù)自身的識別情況做出相應處理, 對應流程如下圖所示:

接收節(jié)點收到ping/meet消息時, 執(zhí)行解析消息頭和消息體流程:

  • 解析消息頭過程:

消息頭包含了發(fā)送節(jié)點的信息, 如果發(fā)送節(jié)點是新節(jié)點且消息是meet類型, 則加入到本地節(jié)點列表; 如果是已知節(jié)點, 則嘗試更新發(fā)送節(jié)點的狀態(tài), 如槽映射關系、 主從角色等狀態(tài)。

  • 解析消息體過程:

如果消息體的clusterMsgDataGossip數(shù)組包含的節(jié)點是新節(jié)點, 則嘗試發(fā)起與新節(jié)點的meet握手流程; 如果是已知節(jié)點, 則根據(jù)cluster MsgDataGossip中的flags字段判斷該節(jié)點是否下線, 用于故障轉移。
消息處理完后回復pong消息, 內(nèi)容同樣包含消息頭和消息體, 發(fā)送節(jié)點接收到回復的pong消息后, 采用類似的流程解析處理消息并更新與接收節(jié)點最后通信時間, 完成一次消息通信。

節(jié)點選擇

        雖然Gossip協(xié)議的信息交換機制具有天然的分布式特性, 但它是有成本的。 由于內(nèi)部需要頻繁地進行節(jié)點信息交換, 而ping/pong消息會攜帶當前節(jié)點和部分其他節(jié)點的狀態(tài)數(shù)據(jù), 勢必會加重帶寬和計算的負擔。 Redis集群內(nèi)節(jié)點通信采用固定頻率(定時任務每秒執(zhí)行10次) 。 因此節(jié)點每次選擇需要通信的節(jié)點列表變得非常重要。 通信節(jié)點選擇過多雖然可以做到信息及時交換但成本過高。 節(jié)點選擇過少會降低集群內(nèi)所有節(jié)點彼此信息交換頻率,從而影響故障判定、 新節(jié)點發(fā)現(xiàn)等需求的速度。 因此Redis集群的Gossip協(xié)議需要兼顧信息交換實時性和成本開銷, 通信節(jié)點選擇的規(guī)則如下圖所示

        根據(jù)通信節(jié)點選擇的流程可以看出消息交換的成本主要體現(xiàn)在單位時間選擇發(fā)送消息的節(jié)點數(shù)量和每個消息攜帶的數(shù)據(jù)量。

1.選擇發(fā)送消息的節(jié)點數(shù)量

        集群內(nèi)每個節(jié)點維護定時任務默認每秒執(zhí)行10次, 每秒會隨機選取5個節(jié)點找出最久沒有通信的節(jié)點發(fā)送ping消息, 用于保證Gossip信息交換的隨機性。 每100毫秒都會掃描本地節(jié)點列表, 如果發(fā)現(xiàn)節(jié)點最近一次接受pong消息的時間大于cluster_node_timeout/2, 則立刻發(fā)送ping消息, 防止該節(jié)點信息太長時間未更新。 根據(jù)以上規(guī)則得出每個節(jié)點每秒需要發(fā)送ping消息的數(shù)
量=1+10*num(node.pong_received>cluster_node_timeout/2) , 因此cluster_node_timeout參數(shù)對消息發(fā)送的節(jié)點數(shù)量影響非常大。 當我們的帶寬資源緊張時, 可以適當調(diào)大這個參數(shù), 如從默認15秒改為30秒來降低帶寬占用率。 過度調(diào)大cluster_node_timeout會影響消息交換的頻率從而影響故障轉移、 槽信息更新、 新節(jié)點發(fā)現(xiàn)的速度。 因此需要根據(jù)業(yè)務容忍度和資源消耗進行平衡。 同時整個集群消息總交換量也跟節(jié)點數(shù)成正比。

2.消息數(shù)據(jù)量

        每個ping消息的數(shù)據(jù)量體現(xiàn)在消息頭和消息體中, 其中消息頭主要占用空間的字段是myslots[CLUSTER_SLOTS/8], 占用2KB, 這塊空間占用相對固定。 消息體會攜帶一定數(shù)量的其他節(jié)點信息用于信息交換。 具體數(shù)量見以下偽代碼:

def get_wanted():
    int total_size = size(cluster.nodes)
    
    # 默認包含節(jié)點總量的1/10
    594int wanted = floor(total_size/10);
    if wanted < 3:
    # 至少攜帶3個其他節(jié)點信息
    wanted = 3;
    if wanted > total_size -2 :
    # 最多包含total_size - 2個
    wanted = total_size - 2;
    return wanted;

        根據(jù)偽代碼可以看出消息體攜帶數(shù)據(jù)量跟集群的節(jié)點數(shù)息息相關, 更大的集群每次消息通信的成本也就更高, 因此對于Redis集群來說并不是大而全的集群更好, 對于集群規(guī)模控制的建議見之后“集群運維”。

其他網(wǎng)址

《Redis開發(fā)與運維》=> 第10章 集群=> 10.3 節(jié)點通信

到此這篇關于Redis集群節(jié)點通信過程/原理的文章就介紹到這了,更多相關Redis集群節(jié)點通信內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!

相關文章

  • Redis Scan命令的基本使用方法

    Redis Scan命令的基本使用方法

    這篇文章主要給大家介紹了關于Redis中Scan命令的基本使用方法,文中通過示例代碼介紹的非常詳細,對大家學習或者使用Redis具有一定的參考學習價值,需要的朋友們下面來一起學習學習吧
    2019-12-12
  • Redis中ZSet的具體使用

    Redis中ZSet的具體使用

    本文主要介紹了Redis中ZSet的具體使用,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2022-07-07
  • Redis可視化工具Redis?Desktop?Manager的具體使用

    Redis可視化工具Redis?Desktop?Manager的具體使用

    本文主要介紹了Redis可視化工具Redis?Desktop?Manager的具體使用,文中通過示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2021-12-12
  • redis?zrange?與?zrangebyscore的區(qū)別解析

    redis?zrange?與?zrangebyscore的區(qū)別解析

    這篇文章主要介紹了redis?zrange與zrangebyscore的區(qū)別,本文給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2023-06-06
  • redis復制集群搭建的實現(xiàn)

    redis復制集群搭建的實現(xiàn)

    redis 復制集群是開發(fā)中一種比較常用的集群模式,本文主要介紹了redis復制集群搭建的實現(xiàn),文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2022-08-08
  • Redis分布式非公平鎖的使用

    Redis分布式非公平鎖的使用

    分布式鎖很多人都能接觸到,本文主要介紹了Redis分布式非公平鎖,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2021-08-08
  • Redis集群Lettuce主從切換問題解決方案

    Redis集群Lettuce主從切換問題解決方案

    這篇文章主要為大家介紹了Redis集群Lettuce主從切換問題解決方案,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2023-07-07
  • Redis 哨兵機制及配置實現(xiàn)

    Redis 哨兵機制及配置實現(xiàn)

    本文主要介紹了Redis 哨兵機制及配置實現(xiàn),文中通過示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-03-03
  • Redis實現(xiàn)排行榜及相同積分按時間排序功能的實現(xiàn)

    Redis實現(xiàn)排行榜及相同積分按時間排序功能的實現(xiàn)

    這篇文章主要介紹了Redis實現(xiàn)排行榜及相同積分按時間排序,本文通過實例代碼給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2022-08-08
  • Redis偶發(fā)連接失敗案例實戰(zhàn)記錄

    Redis偶發(fā)連接失敗案例實戰(zhàn)記錄

    這篇文章主要給大家介紹了關于Redis偶發(fā)連接失敗的相關資料,文中通過示例代碼介紹的非常詳細,對大家學習或者使Redis具有一定的參考學習價值,用需要的朋友們下面隨著小編來一起學習學習吧
    2018-10-10

最新評論