哨兵节点

作用:由一个或多个Sentinel实例组成的系统,可以监视多个主从服务器,在其监视的主服务器下线时,自动将属下的某个从服务器升级为新的主服务器,保证可用性。

Sentinel是一个运行在特殊模式下的Redis服务器,但是不使用数据库,在启动时不需要加载RDB或AOF文件。

哨兵节点如何监视主/从服务器:

  • 哨兵节点启动时将初始化masters字典,储存监视主服务器的IP和端口
  • 哨兵节点初始化结束时,将建立与主服务器的网络连接,成为主服务器的客户端。哨兵节点和主节点间将建立两条异步连接,一条是命令连接,用于向主服务器发送命令接受回复,另一条是订阅连接,订阅主服务器的__sentinel__:hello频道。命令连接发送的命令会发送给服务器的__sentinel__:hello频道
  • 哨兵节点每10秒向主服务器发送一条INFO命令,获取主服务器自身的状态和其属下从服务器的信息;每10秒也会向从服务器发送一条INFO命令,获取器自身状态和其主服务器信息
  • 哨兵节点每2秒会向其监视的所有服务器发送命令,此命令会向服务器的__sentinel__:hello频道发送信息,内容为哨兵本身的信息,如果接受命令的是主服务器,命令中会带有此主服务器的信息,否则会带有此从服务器所复制的主服务器的信息
  • 每一个哨兵节点向服务器发送的信息都会被同样监视这台服务器的其他哨兵节点接收,在发现有监视同一台服务器的其他哨兵节点后,哨兵内部也会维护一个哨兵dict,并互相建立起命令连接
  • 哨兵节点每1秒会向其创建过命令连接的所有实例,包括主服务器、从服务器、其他哨兵节点发送PING,根据返回判断实例状态。如果超出配置的某个时长,就会判断该实例进入主观下线状态。之后会询问同样监视这台服务器的其他哨兵节点,获得足够多的下线判断后,将认为这台实例进入客观下线状态

故障转移

  • 在哨兵节点们观察到主服务器客观下线之后,需要进行故障转移操作。此时需要从监视其的所有哨兵节点中选出一个领头节点进行操作。Redis的选主使用的是RAFT算法
  • 选举出的领头哨兵节点将对这台主服务器的所有从服务器进行评估,排除下线、断线、某个时间内未进行通信的实例,最后选出复制偏移量最大、ID最小的一台从服务器
  • 领头哨兵会向被选中的从服务器发送SLAVEOF no one命令,告知其已被选中,并以比平时更快(每1秒一次)的频率向其发送INFO命令,观察其是否了解自己已经成为了主服务器。之后会向剩余的从服务器发送SLAVEOF命令,告知他们复制新的主服务器
  • 旧的主服务器上线后,哨兵节点会告知他,作为从服务器复制新的主服务器

RAFT算法

  • RAFT算法是一种分布式一致性算法
  • 每个节点可能是三种身份之一:LeaderFollowerCandidate。节点之间交换的消息分为两种,一种是用于宣示自身Leader地位的AppendEntries RPC,下文称之为心跳。另一种是Follower用于参选的RequestVote RPC,下文称之为选票
  • Leader: Leader节点会周期性的向所有Follower发送心跳。如果一个Follower在一段时间内都没收到任何消息,就会认为系统中没有可用的Leader,就会发起选举以选取新的Leader。这里的一段时间是指选举超时时间,每个节点的选举超时时间是从一个固定的区间(例如 150-300 毫秒)随机选择的,随机选择选举超市时间可以确保不会经常出现节点同时开始竞选,频繁平票。Leader在收到epoch高于自身的消息后,会立刻转化为其Follower
  • Follower:Follower会忽略epoch小于自身的消息,收到epoch大于等于自身的消息以后,立刻成为发送消息节点的Follower。收到心跳之后,Follower会返回一次选票,表示认同对方的Leader地位,在同一个epoch中,一个Follower只会投票给一个Candidate,遵循先到先得的原则
  • Candidate:Follower在没有收到心跳超过超时时间后,会立刻使自己的epoch自增1,然后向所有其他节点发送选票。Candidate在三种情况下会脱离Candidate状态:赢得选举成为Leader、输掉选举成为Follower、本次选举超时成为下个epoch的Candidate
  • 节点之间的通信带有epoch(纪元),每个epoch内只会出现至多一个Leader,也有可能没有产生Leader,直接进入下一个epoch