我的编程空间,编程开发者的网络收藏夹
学习永远不晚

Redis集群节点通信过程/原理流程分析

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

Redis集群节点通信过程/原理流程分析

简介

        本文介绍Redis的Cluster(集群)的节点通信的流程。

通信流程

        在分布式存储中需要提供维护节点元数据信息的机制, 所谓元数据是指: 节点负责哪些数据, 是否出现故障等状态信息。 常见的元数据维护方式分为: 集中式和P2P方式。 Redis集群采用P2P的Gossip(流言) 协议,Gossip协议工作原理就是节点彼此不断通信交换信息, 一段时间后所有的节点都会知道集群完整的信息, 这种方式类似流言传播, 如下所示

通信过程说明:

  • 集群中的每个节点都会单独开辟一个TCP通道, 用于节点之间彼此通信, 通信端口号在基础端口上加10000。
  • 每个节点在固定周期内通过特定规则选择几个节点发送ping消息。接收到ping消息的节点用pong消息作为响应。
  • 集群中每个节点通过一定规则挑选要通信的节点, 每个节点可能知道全部节点, 也可能仅知道部分节点, 只要这些节点彼此可以正常通信, 最终它们会达到一致的状态。 当节点出故障、 新节点加入、 主从角色变化、 槽信息变更等事件发生时, 通过不断的ping/pong消息通信, 经过一段时间后所有的节点都会知道整个集群全部节点的最新状态, 从而达到集群状态同步的目的。 

Gossip消息

消息流程

        Gossip协议的主要职责就是信息交换。 信息交换的载体就是节点彼此发送的Gossip消息, 了解这些消息有助于我们理解集群如何完成信息交换。

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

  • meet消息: 用于通知新节点加入。

消息发送者通知接收者加入到当前集群, meet消息通信正常完成后, 接收节点会加入到集群中并进行周期性的ping、 pong消息交换。

  • ping消息: 集群内交换最频繁的消息

 集群内每个节点每秒向多个其他节点发送ping消息, 用于检测节点是否在线和交换彼此状态信息。 ping消息发送封装了自身节点和部分其他节点的状态数据。

  • pong消息: 当接收到ping、 meet消息时, 作为响应消息回复给发送方确认消息正常通信。

pong消息内部封装了自身状态数据。 节点也可以向集群内广播自身的pong消息来通知整个集群对自身状态进行更新。
fail消息: 当节点判定集群内另一个节点下线时, 会向集群内广播一个fail消息, 其他节点接收到fail消息之后把对应节点更新为下线状态。 具体细节将在后面“故障转移”中说明。

消息格式

        所有的消息格式划分为: 消息头和消息体。 消息头包含发送节点自身状态数据, 接收节点根据消息头就可以获取到发送节点的相关数据, 结构如下:

typedef struct {
    char sig[4]; 
    uint32_t totlen; 
    uint16_t ver; 
    uint16_t type; 
    uint16_t count; 
    uint64_t currentEpoch; 
    uint64_t configEpoch; 
    uint64_t offset; 
    char sender[CLUSTER_NAMELEN]; 
    unsigned char myslots[CLUSTER_SLOTS/8]; 
    char slaveof[CLUSTER_NAMELEN]; 
    uint16_t port; 
    uint16_t flags; 
    unsigned char state; 
    unsigned char mflags[3]; 
    union clusterMsgData data ;
} clusterMsg;

        集群内所有的消息都采用相同的消息头结构clusterMsg, 它包含了发送节点关键信息, 如节点id、 槽映射、 节点标识(主从角色, 是否下线) 等。消息体在Redis内部采用clusterMsgData结构声明, 结构如下:

union clusterMsgData {
    
    struct {
        
        clusterMsgDataGossip gossip[1];
    } ping;
    
    
    struct {
        clusterMsgDataFail about;
    } fail;
    // ...
};

        消息体clusterMsgData定义发送消息的数据, 其中ping、 meet、 pong都采用cluster MsgDataGossip数组作为消息体数据, 实际消息类型使用消息头的type属性区分。 每个消息体包含该节点的多个clusterMsgDataGossip结构数据, 用于信息交换, 结构如下:

typedef struct {
    char nodename[CLUSTER_NAMELEN]; 
    uint32_t ping_sent; 
    uint32_t pong_received; 
    char ip[NET_IP_STR_LEN]; 
    uint16_t port; 
    uint16_t flags; 
} clusterMsgDataGossip;

        当接收到ping、 meet消息时, 接收节点会解析消息内容并根据自身的识别情况做出相应处理, 对应流程如下图所示:

接收节点收到ping/meet消息时, 执行解析消息头和消息体流程:

  • 解析消息头过程:

消息头包含了发送节点的信息, 如果发送节点是新节点且消息是meet类型, 则加入到本地节点列表; 如果是已知节点, 则尝试更新发送节点的状态, 如槽映射关系、 主从角色等状态。

  • 解析消息体过程:

如果消息体的clusterMsgDataGossip数组包含的节点是新节点, 则尝试发起与新节点的meet握手流程; 如果是已知节点, 则根据cluster MsgDataGossip中的flags字段判断该节点是否下线, 用于故障转移。
消息处理完后回复pong消息, 内容同样包含消息头和消息体, 发送节点接收到回复的pong消息后, 采用类似的流程解析处理消息并更新与接收节点最后通信时间, 完成一次消息通信。

节点选择

        虽然Gossip协议的信息交换机制具有天然的分布式特性, 但它是有成本的。 由于内部需要频繁地进行节点信息交换, 而ping/pong消息会携带当前节点和部分其他节点的状态数据, 势必会加重带宽和计算的负担。 Redis集群内节点通信采用固定频率(定时任务每秒执行10次) 。 因此节点每次选择需要通信的节点列表变得非常重要。 通信节点选择过多虽然可以做到信息及时交换但成本过高。 节点选择过少会降低集群内所有节点彼此信息交换频率,从而影响故障判定、 新节点发现等需求的速度。 因此Redis集群的Gossip协议需要兼顾信息交换实时性和成本开销, 通信节点选择的规则如下图所示

        根据通信节点选择的流程可以看出消息交换的成本主要体现在单位时间选择发送消息的节点数量和每个消息携带的数据量。

1.选择发送消息的节点数量

        集群内每个节点维护定时任务默认每秒执行10次, 每秒会随机选取5个节点找出最久没有通信的节点发送ping消息, 用于保证Gossip信息交换的随机性。 每100毫秒都会扫描本地节点列表, 如果发现节点最近一次接受pong消息的时间大于cluster_node_timeout/2, 则立刻发送ping消息, 防止该节点信息太长时间未更新。 根据以上规则得出每个节点每秒需要发送ping消息的数
量=1+10*num(node.pong_received>cluster_node_timeout/2) , 因此cluster_node_timeout参数对消息发送的节点数量影响非常大。 当我们的带宽资源紧张时, 可以适当调大这个参数, 如从默认15秒改为30秒来降低带宽占用率。 过度调大cluster_node_timeout会影响消息交换的频率从而影响故障转移、 槽信息更新、 新节点发现的速度。 因此需要根据业务容忍度和资源消耗进行平衡。 同时整个集群消息总交换量也跟节点数成正比。

2.消息数据量

        每个ping消息的数据量体现在消息头和消息体中, 其中消息头主要占用空间的字段是myslots[CLUSTER_SLOTS/8], 占用2KB, 这块空间占用相对固定。 消息体会携带一定数量的其他节点信息用于信息交换。 具体数量见以下伪代码:

def get_wanted():
    int total_size = size(cluster.nodes)
    
    # 默认包含节点总量的1/10
    594int wanted = floor(total_size/10);
    if wanted < 3:
    # 至少携带3个其他节点信息
    wanted = 3;
    if wanted > total_size -2 :
    # 最多包含total_size - 2个
    wanted = total_size - 2;
    return wanted;

        根据伪代码可以看出消息体携带数据量跟集群的节点数息息相关, 更大的集群每次消息通信的成本也就更高, 因此对于Redis集群来说并不是大而全的集群更好, 对于集群规模控制的建议见之后“集群运维”。

其他网址

《Redis开发与运维》=> 第10章 集群=> 10.3 节点通信

到此这篇关于Redis集群节点通信过程/原理的文章就介绍到这了,更多相关Redis集群节点通信内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

Redis集群节点通信过程/原理流程分析

下载Word文档到电脑,方便收藏和打印~

下载Word文档

编程热搜

  • Python 学习之路 - Python
    一、安装Python34Windows在Python官网(https://www.python.org/downloads/)下载安装包并安装。Python的默认安装路径是:C:\Python34配置环境变量:【右键计算机】--》【属性】-
    Python 学习之路 - Python
  • chatgpt的中文全称是什么
    chatgpt的中文全称是生成型预训练变换模型。ChatGPT是什么ChatGPT是美国人工智能研究实验室OpenAI开发的一种全新聊天机器人模型,它能够通过学习和理解人类的语言来进行对话,还能根据聊天的上下文进行互动,并协助人类完成一系列
    chatgpt的中文全称是什么
  • C/C++中extern函数使用详解
  • C/C++可变参数的使用
    可变参数的使用方法远远不止以下几种,不过在C,C++中使用可变参数时要小心,在使用printf()等函数时传入的参数个数一定不能比前面的格式化字符串中的’%’符号个数少,否则会产生访问越界,运气不好的话还会导致程序崩溃
    C/C++可变参数的使用
  • css样式文件该放在哪里
  • php中数组下标必须是连续的吗
  • Python 3 教程
    Python 3 教程 Python 的 3.0 版本,常被称为 Python 3000,或简称 Py3k。相对于 Python 的早期版本,这是一个较大的升级。为了不带入过多的累赘,Python 3.0 在设计的时候没有考虑向下兼容。 Python
    Python 3 教程
  • Python pip包管理
    一、前言    在Python中, 安装第三方模块是通过 setuptools 这个工具完成的。 Python有两个封装了 setuptools的包管理工具: easy_install  和  pip , 目前官方推荐使用 pip。    
    Python pip包管理
  • ubuntu如何重新编译内核
  • 改善Java代码之慎用java动态编译

目录