Redis Cluster采用P2P的Gossip协议进行通信,节点之间不断的交换信息,这些信息包括节点负责哪些slot、是否出现故障等信息
集群中的每个节点通过一定的规则挑选要通信的节点,每个节点可能知道其他全部节点,也可能仅知道部分节点,只要这些节点之间可以正常通信,最终它们会达到一致状态,当节点出现故障、新节点加入、主从角色变化、slot信息变更等事件发生时,通过不断的ping/pong消息通信,经过一段时间后所有的节点都会知道整个集群全部节点的最新状态,从而达到集群状态同步的目的。
Gossip协议的主要职责就是信息交换。信息交换的载体就是节点彼此发送的Gossip消息,常用的Gossip消息可分为:ping
消息、pong
消息、meet
消息、fail
消息等。
一个Gossip的消息头中包含的信息:
消息体包含的信息:
虽然Gossip协议的信息交换机制具有天然的分布式特性,但它是有成本的。由于内部需要频繁地进行节点信息交换,而ping/pong消息会携带当前节点和部分其他节点的状态数据,势必会加重带宽和计算的负担。Redis集群内节点通信采用固定频率(定时任务每秒执行10次)。因此节点每次选择需要通信的节点列表变得非常重要。通信节点选择过多虽然可以做到信息及时交换但成本过高。节点选择过少会降低集群内所有节点彼此信息交换频率,从而影响故障判定、新节点发现等需求的速度。因此Redis集群的Gossip协议需要兼顾信息交换实时性和成本开销,通信节点选择的规则如下:
cluster_node_timeout/2
,则立刻发送ping消息,防止该节点信息太长时间未更新1+10*num(node.pong_received>cluster_node_timeout/2)
,因此cluster_node_timeout
参数对消息发送的节点数量影响非常大真实世界的机房网络往往并不是风平浪静的,它们经常会发生各种各样的小问题。比如网络抖动就是非常常见的一种现象,突然之间部分连接变得不可访问,然后很快又恢复正常。为解决这种问题,Redis Cluster 提供了一个配置选项cluster-node-timeout
,表示当某个节点持续 timeout 的时间失时,才可以认定该节点出现故障,需要进行主从切换。如果没有这个选项,网络抖动会导致主从频繁切换 (数据的重新复制)。
还有另外一个选项cluster-slave-validity-factor
作为倍乘系数来放大这个超时时间来宽松容错的紧急程度。如果这个系数为零,那么主从切换是不会抗拒网络抖动的,即cluster-slave-validity-factor=0
则cluster-node-timeout
配置实效,只要一发现某个节点失联,立马进行主从切换;如果这个系数大于 0,它就成了主从切换的松弛系数,cluster-node-timeout * cluster-slave-validity-factor
的时间,将作为主从切换之间的最大容忍时间,例如cluster-node-timeout=5000,cluster-slave-validity-factor=3
,那么在一个节点失联15s之后,才可以进行主从切换。