原文网址:Redis集群--节点通信的过程(原理)_IT利刃出鞘的博客-CSDN博客

简介

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

通信流程

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

通信过程说明:

  1. 集群中的每个节点都会单独开辟一个TCP通道, 用于节点之间彼此通信, 通信端口号在基础端口上加10000。
  2. 每个节点在固定周期内通过特定规则选择几个节点发送ping消息。接收到ping消息的节点用pong消息作为响应。
  3. 集群中每个节点通过一定规则挑选要通信的节点, 每个节点可能知道全部节点, 也可能仅知道部分节点, 只要这些节点彼此可以正常通信, 最终它们会达到一致的状态。 当节点出故障、 新节点加入、 主从角色变化、 槽信息变更等事件发生时, 通过不断的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; /* 消息类型,用于区分meet,ping,pong等消息 */uint16_t count; /* 消息体包含的节点数量, 仅用于meet,ping,ping消息类型*/uint64_t currentEpoch; /* 当前发送节点的配置纪元 */uint64_t configEpoch; /* 主节点/从节点的主节点配置纪元 */uint64_t offset; /* 复制偏移量 */char sender[CLUSTER_NAMELEN]; /* 发送节点的nodeId */unsigned char myslots[CLUSTER_SLOTS/8]; /* 发送节点负责的槽信息 */char slaveof[CLUSTER_NAMELEN]; /* 如果发送节点是从节点, 记录对应主节点的nodeId */uint16_t port; /* 端口号 */uint16_t flags; /* 发送节点标识,区分主从角色, 是否下线等 */unsigned char state; /* 发送节点所处的集群状态 */unsigned char mflags[3]; /* 消息标识 */union clusterMsgData data /* 消息正文 */;
} clusterMsg;

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

union clusterMsgData {/* ping,meet,pong消息体*/struct {/* gossip消息结构数组 */clusterMsgDataGossip gossip[1];} ping;/* FAIL 消息体 */struct {clusterMsgDataFail about;} fail;// ...
};

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

typedef struct {char nodename[CLUSTER_NAMELEN]; /* 节点的nodeId */uint32_t ping_sent; /* 最后一次向该节点发送ping消息时间 */uint32_t pong_received; /* 最后一次接收该节点pong消息时间 */char ip[NET_IP_STR_LEN]; /* IP */uint16_t port; /* 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/10594int 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集群--Cluster--节点通信的过程(原理)相关推荐

  1. Redis集群--Cluster--故障转移的过程(原理)

    原文网址:Redis集群--Cluster--故障转移的过程(原理)_IT利刃出鞘的博客-CSDN博客_redis集群故障转移 简介 本文介绍Redis集群(Cluster)的故障转移的流程. 故障发 ...

  2. Redis集群cluster环境(快速搭建过程10分钟)

    安装环境CentOS Linux release 7.5.1804 (Core) 如果服务器没有连接网络,请按步骤自行百度其离线方式 话不多说,开整!!! 一.安装redis #下载至/home/in ...

  3. redis集群添加节点报错Either the node already knows other nodes (check with CLUSTER NODES) or contains some k

    [README] redis集群添加节点报错 [ERR] Node 192.168.163.202:6380 is not empty. Either the node already knows o ...

  4. Redis集群添加节点

    Redis集群添加节点 1:首先把需要添加的节点启动 cd /usr/local/cluster/ mkdir 7006 cp /usr/local/cluster/redis.conf  /usr/ ...

  5. 机器从零到 K8S 集群 Worker 节点的安装过程

    最近基于 Hyper-V 虚拟机搭了一个单节点的 K8S,过程没有记录下来 本次实践从零开始搭建一个 K8S Slave 节点 机器从零到 K8S 集群 Slave 节点的安装过程 实践环境 安装 L ...

  6. Redis集群master节点挂掉之后的处理方式

    大家好,今天分享Redis集群master节点挂掉之后的处理方式 我们前面做的主从复制 是这样的一个结构 要改成这样 将6303的主节点接到6302 127.0.0.1:6303> SLAVEO ...

  7. shell脚本遍历redis集群所有节点日志,并入库到hadoop中,进行数据分析

    shell脚本遍历redis集群所有节点,并入库到hadoop中的数据库中,进行数据分析,在此留存,以备他用 [AAAAAAnilRedis@FXYY-FS-redis2 ~]$ cat /home/ ...

  8. 通过cluster reshard实现Redis集群缩减节点实战【详细步骤】

    今年由于新冠疫情的影响,可能很多同学都被公司要求压缩服务器成本.这两天,公司领导把小眼睛瞟到笔者开发环境里那个可怜的redis集群上.好吧,那么我们就来操作一下缩减redis集群. 查看cluster ...

  9. 分布式Redis集群--Cluster架构

    Cluster架构 Redis哨兵与Cluster集群模式对比 1. 哨兵模式 Redis3.0之前一般是通过哨兵工具来监测master节点的状态,若master节点宕机,则哨兵集群会进行主从切换,从 ...

  10. Redis集群Cluster部署

    这篇Redis 集群部署笔记参考的书籍资料是: <Redis入门指南>第二版,作者:李子骅 第8章 <Redis开发与运维> 作者:付磊 第10章 以下是学习笔记,记录了Red ...

最新文章

  1. 支付宝何以支撑双十一4200万次/秒的数据库请求峰值?
  2. python作图一览
  3. CentOS 6.5 下安装 Redis 2.8.7
  4. 习题2.5 两个有序链表序列的合并 (15 分)
  5. 让人“蛋碎”的ie兼容问题
  6. python访问服务器注册表,如何在Python中使用写入权限打开Windows注册表
  7. 服务器系统防火墙例外,Windows Server 2012设置端口例外、防火墙设置方法
  8. datagrid——jQuery EasyUI
  9. windows系统清理磁盘临时文件,及缓冲文件,及离线文件和空闲文件
  10. 案例全是电商零售,B2B的用户画像怎么做???
  11. MariaDB忘记root密码
  12. AAPT: error: resource android:attr/dialogCornerRadius not found.
  13. 视频:Microsoft PDC 09,算法及数据结构内容及其他
  14. 超火的ipad procreate必备神仙笔刷资源打包下载
  15. Oracle Solaris系统,诺禾
  16. android开发 问卷调查案例_android 实现调查问卷-单选-多选
  17. IDEA打包jar包的多种方式
  18. 计算机网络谢希仁课后答案详解+计算机网络释疑与习题解答PDF+各章重点题目
  19. ESP8266 FS库函数学习
  20. android跳转到微信小程序

热门文章

  1. 动态添加element标签,数据操作
  2. js中this的作用域
  3. 工业互联网标识解析体系
  4. Stream.of()用法示例
  5. Django文档是如何组织的?
  6. 163邮箱服务器注册不了怎么办,outlook邮箱添加163邮箱账户失败该怎么办?
  7. 微信小程序识别图片并提取文字_微信小程序图片上传(文字识别)
  8. 《OpenGL编程指南(原书第9版)》——第3章 3.0OpenGL绘制方式
  9. python制作圆形按钮_圆形按钮tkinter python
  10. 如何在苹果手机上进行自动化测试!!!!!可以尝试配置一下