通信流程
在分布式存储中需要提供维护节点元数据信息的机制,所谓元数据是指:节点负责哪些数据,是否出现故障等状态信息。而常见的元素据维护方式为:集中式和P2P方式。redis集群采用P2P的Gossip协议,Gossip协议工作原理就是节点彼此不断通信交换信息,一段事件后所有的节点都会知道集群完整的信息,这种方式类似流言传播。
节点彼此传播消息通信过程说明:
1>集群中的每个节点都会单独开辟一个TCP通道,用于节点之间彼此通信,通信端口号在基础端口上加10000,不如6379这个节点的通信端口看起来是这样的:16379
2>每个节点在固定周期内通过特定规则选择几个节点发送ping消息。
3>接收到ping消息的节点用pong消息作为响应。
集群中每个节点通过一定规则挑选要通信的节点,每个节点可能知道全部节点,也可能仅知道部分节点,只要这些节点彼此可以正常通信,最终它们会达到一致的状态。当节点出故障,新节点加入,主从角色变化,槽信息变更等事件发生时,通过不断ping/pong消息通信,经过一段时间后所有的节点都会知道整个集群全部节点的最新状态,从而达到集群状态同步的目的。
Gossip(八卦,流言)消息
Gossip协议的主要职责就是信息交换。信息交换的载体就是节点彼此发送的Gossip消息。
常用的Gossip消息分:ping消息,pong消息,meet消息,fail消息。
不同的消息通信模式meet消息:用于通知新的节点加入。消息发送者通知接收者加入到当前集群,meet消息通信正常完成后,接收节点会加入到集群中兵进行周期性的ping,pong消息交换。
ping消息:集群内交换最频繁的消息,集群内每个节点每秒向多个其他节点发送ping消息,用于检测节点是否在线和交换彼此状态信息。ping消息发送封装了自身节点和部分其他节点的状态数据。
pong消息:当接收到ping消息时,作为响应消息回复给发送方确认消息正常通信。pong消息内部封装了自身状态数据。节点也可以向集群内广播自身的pong消息来通知整个集群对自身状态进行更新。
fail消息:当节点判定集群内另一个节点下线时,会向集群内广播一个fail消息,其他节点接收到fail消息之后把对应节点更新为下线状态。
所有的消息格式划分为:消息头+消息体。看起来来会是这样的:
Gossip消息当接收到ping,meet消息时,接收节点会解析消息内容并根据自身的识别情况来做解析。
消息解析流程节点选择
虽然Gossip协议的信息交换机制具有天然的分布式特性,但它是有成本的。由于内部需要频繁的进行节点信息交换,而ping/pong消息会携带当前节点和部分其他节点的状态数据,势必会家长代换和计算的负担。redis集群内节点通信采用固定频率(定时任务每秒执行10次)。因此节点每次选择需要通信的节点列表变得非常重要。通信节点选择过多虽然可以做到信息及时交换但成本过高。节点选择过少会降低集群内所有节点彼此信息交换频率,从而影响故障判定,新节点发现等需求的速度。因此redis集群的Gossip协议需要兼顾信息交换实时性和成本开销。
1>如何选择要发送消息的节点,以及发送的频率(给谁发,发多少个)
首先我们设定所呈现的过程的时间是1秒,一共6个节点,发送方节点为6379
6379会向其他的(不包括自己的所有节点中随机选5个,这里一共就6个所以是除自己以外的其他5个节点)节点发送一条消息,这条消息会被其他的5个节点接收,类似于广播。然后每隔100毫秒扫描一次本地节点列表,如果发现节点最近一次接受pong消息的时间大于cluster_node_timeout/2,则立即发送ping消息。(假设满足条件的节点为红色节点,Num=2)1秒内要扫描10次,所以要给这个节点发10次消息。
所以一共要发的消息个数为:count=1+Num*10
2>如何选择额外要被发送其他节点的个数(一个消息多大)
每个ping消息除了发送节点自身的消息外,还要额外发送其他节点的一些信息,额外发几个其他节点的信息呢?这里有计算公式:
设定N是集群个数,A是携带其他节点的数量,a=floor(N/10)
所以基于我们这个场景,这一秒钟一共要发21条消息,额外携带其他节点的个数为3.
网友评论