一、Gossip 在Redis-Cluster中如何作用
redis集群之间采用的Gossip协议进行通信。
redis集群中每台机器上都保存了一份元数据,如果有节点出现了元数据变更会不断的新的元数据发给其他节点,让其他节点也进行元数据变更。
这个跟zookeeper很不一样,ZK集群的元数据是集中式的,且是强一致性,主要由Leader外带提供写操作。
在分布式系统中,需要提供维护节点元数据信息的机制,所谓元数据是指:节点负责哪些数据、主从属性、是否出现故障等状态信息。常见的元数据维护方式分为:集中式和无中心式。Redis-Cluster采用Gossip协议实现了无中心式。
节点通信基础
Redis-Cluster中的每个 Redis 实例监听两个 TCP 端口,6379(默认)用于服务客户端查询,16379(默认服务端口+10000)用于集群内部通信。集群中节点通信方式如下:
每个节点在固定周期内通过特定规则选择几个节点发送ping消息;
接收到ping消息的节点用pong消息作为响应;
交换的信息
集群间交换的信息有:故障信息、节点的增加和移除、hash slot 信息,等等
二、Gossip协议
原理
Gossip协议基本思想就是:
一个节点想要分享一些信息给网络中的其他的一些节点。
于是,它周期性的随机选择一些节点,并把信息传递给这些节点。
这些收到信息的节点接下来会做同样的事情,即把这些信息传递给其他一些随机选择的节点。
一般而言,信息会周期性的传递给N个目标节点,而不只是一个。这个N被称为fanout(这个单词的本意是扇出)。
特点
可扩展性
Gossip协议是可扩展的,因为它只需要O(logN) 个周期就能把消息传播给所有节点。某个节点在往固定数量节点传播消息过程中,并不需要等待确认(ack),并且,即使某条消息传播过程中丢失,它也不需要做任何补偿措施。大哥比方,某个节点本来需要将消息传播给4个节点,但是由于网络或者其他原因,只有3个消息接收到消息,即使这样,这对最终所有节点接收到消息是没有任何影响的。
如下表格所示,假定fanout=4,那么在节点数分别是20、40、80、160时,消息传播到所有节点需要的循环次数对比,在节点成倍扩大的情况下,循环次数并没有增加很多。所以,Gossip协议具备可扩展性:
失败容错
Gossip也具备失败容错的能力,即使网络故障等一些问题,Gossip协议依然能很好的运行。因为一个节点会多次分享某个需要传播的信息,即使不能连通某个节点,其他被感染的节点也会尝试向这个节点传播信息。
健壮性
Gossip协议下,没有任何扮演特殊角色的节点(比如leader等)。任何一个节点无论什么时候下线或者加入,并不会破坏整个系统的服务质量。
Gossip消息种类
Gossip协议的主要职责就是信息交换。信息交换的载体就是节点彼此发送的Gossip消息,常用的Gossip消息可分为:ping消息、pong消息、meet消息、fail消息。
meet消息:用于通知新节点加入。消息发送者通知接收者加入到当前集群,meet消息通信正常完成后,接收节点会加入到集群中并进行周期性的ping、pong消息交换;
ping消息:集群内交换最频繁的消息,集群内每个节点每秒向多个其它节点发送ping消息,用于检测节点是否在线和交换彼此状态信息。ping消息发送封装了自身节点和部分其它节点的状态数据;
pong消息:当接收到ping、meet消息时,作为响应消息回复给发送方确认消息正常通信。pong消息内部封装了自身状态数据。节点也可以向集群内广播自身的pong消息来通知整个集群对自身状态进行更新;
fail消息:当节点判定集群内另一个节点下线时,会向集群内广播一个fail消息,其他节点接收到fail消息之后把对应节点更新为下线状态;
在 cluster-node-timeout 内,某个节点一直没有返回 pong,那么就被认为 pfail
如果一个节点认为某个节点 pfail 了,那么会在 gossip ping 消息中,ping 给其他节点,如果超过半数的节点都认为 pfail 了,那么就会变成 fail
ping 消息深入
ping 很频繁,而且要携带一些元数据,所以可能会加重网络负担
每个节点每秒会执行 10 次 ping,每次会选择 5 个最久没有通信的其他节点
当然如果发现某个节点通信延时达到了 cluster_node_timeout / 2,那么立即发送 ping,避免数据交换延时过长,落后的时间太长了
比如说,两个节点之间都 10 分钟没有交换数据了,那么整个集群处于严重的元数据不一致的情况,就会有问题
所以 cluster_node_timeout 可以调节,如果调节比较大,那么会降低发送的频率
每次 ping,一个是带上自己节点的信息,还有就是带上 1/10 其他节点的信息,发送出去,进行数据交换
至少包含 3 个其他节点的信息,最多包含总节点 -2 个其他节点的信息