深度原理学习–Redis集群( 三 )


心跳和gossip消息
集群中的节点会不停的互相交换ping pong包,ping pong包具有相同的结构,只是类型不同,ping pong包合在一起叫做心跳包 。
通常节点会发送ping包并接收接收者返回的pong包,不过这也不是绝对,节点也有可能只发送pong包,而不需要让接收者发送返回包,这种操作通常用于广播一个新的配置信息 。
节点会每个几秒钟就发送一定数量的ping包 。如果一个节点超过二分之一NODE_TIME时间没有收到来自某个节点ping或pong包,那么就会在NODE_TIMEOUT之前像该节点发送ping包,在NODE_TIMEOUT之前,节点会尝试TCP重连,避免由于TCP连接问题而误以为节点不可达 。
心跳包内容
前面我们说了,ping和pong包的结构是相同的,下面就来具体看一下包的内容 。
ping和pong包的内容可以分为header和gossip消息两部分,其中header包含以下信息:

  • NODE ID是一个160bit的伪随机字符串,它是节点在集群中的唯一标识
  • currentEpoch和configEpoch字段
  • node flag,标识节点是master还是slave,另外还有一些其他的标识位
  • 节点提供服务的hash slot的bitmap
  • 发送者的TCP端口
  • 发送者认为的集群状态(down or ok)
  • 如果是slave,则包含master的NODE ID
gossip包含了该节点认为的其他节点的状态,不过不是集群的全部节点 。具体有以下信息:
  • NODE ID
  • 节点的IP和端口
  • NODE flags
gossip消息在错误检测和节点发现中起着重要的作用 。
错误检测
错误检测用于识别集群中的不可达节点是否已下线,如果一个master下线,会将它的slave提升为master 。如果无法提升,则集群会处于错误状态 。在gossip消息中,NODE flags的值包括两种PFAIL和FAIL 。
PFAIL flag
如果一个节点发现另外一个节点不可达的时间超过NODE_TIMEOUT,则会将这个节点标记为PFAIL,也就是Possible failure(可能下线) 。节点不可达是说一个节点发送了ping包,但是等待了超过NODE_TIMEOUT时间仍然没有收到回应 。这也就意味着,NODE_TIMEOUT必须大于一个网络包来回的时间 。
FAIL flag
PFAIL标志只是一个节点本地的信息,为了使slave提升为master,需要将PFAIL升级为FAIL 。PFAIL升级为FAIL需要满足一些条件:
  • A节点将B节点标记为PFAIL
  • A节点通过gossip消息收集其他大部分master节点标识的B节点的状态
  • 大部分master节点在NODE_TIMEOUT * FAIL_REPORT_VALIDITY_MULT时间段内,标识B节点为PFAIL或FAIL
如果满足以上条件,A节点会将B节点标识为FAIL并且向所有节点发送B节点FAIL的消息 。收到消息的节点也都会将B标为FAIL 。
FAIL状态是单向的,只能从PFAIL升级为FAIL,而不能从FAIL降为PFAIL 。不过存在一些清除FAIL状态的情况:
  • 节点重新可达,并且是slave节点
  • 节点重新可达,并且是master节点,但是不提供任何slot服务
  • 节点重新可达,并且是master节点,但是长时间没有slave被提升为master来顶替它
PFAIL提升到FAIL使用的是一种弱协议:
  • 节点收集的状态不在同一时间点,我们会丢弃时间较早的报告信息,但是也只能保证节点的状态在一段时间内大部分master达成了一致
  • 检测到一个FAIL后,需要通知所有节点,但是没有办法保证每个节点都能成功收到消息
由于是弱协议,Redis Cluster只要求所有节点对某个节点的状态最终保持一致 。如果大部分master认为某个节点FAIL,那么最终所有节点都会将其标为FAIL 。而如果只有一小部分master节点认为某个节点FAIL,slave并不会被提升为master,因此,FAIL状态将会被清除 。
搭建
原理说了这么多,我们一定要来亲自动手搭建一个Redis Cluster,下面演示一个在一台机器上模拟搭建3主3从的Redis Cluster 。当然,如果你想了解更多Redis Cluster的其他原理,可以点击阅读原文查看官网的介绍 。
Redis环境
首先要搭建起我们需要的Redis环境,这里启动6个Redis实例,端口号分别是6379、6380、6479、6480、6579、6580
拷贝6份Redis配置文件并进行如下修改(以6379为例,端口号和配置文件根据需要修改):
1port 6379
2cluster-enabled yes
3cluster-config-file nodes6379.conf
4Appendonly yes
配置文件的名称也需要修改,修改完成后,分别启动6个实例(图片中有一个端口号改错了……) 。
深度原理学习–Redis集群

文章插图
Redis instances
创建Redis Cluster
实例启动完成后,就可以创建Redis Cluster了,如果Redis的版本是3.x或4.x,需要使用一个叫做redis-trib的工具,而对于Redis5.0之后的版本,Redis Cluster的命令已经集成到了redis-cli中了 。这里我用的是Redis5,所以没有再单独安装redis-trib工具 。


推荐阅读