天天看点

7.4 Redis哨兵之实现原理

1.三个定时任务

(1).每10秒info

Sentinel每10秒会对master执行info操作,获取master的slave节点信息,Sentinel拿到slave信息之后,每10秒也会执行info操作,去发现slave的从节点。起到Sentinel感知Redis的作用。

7.4 Redis哨兵之实现原理

(2).每2秒发布订阅

Sentinel之间通过master节点的_sentinel_:hello频道来交换信息,即每个Sentinel都会订阅_sentinel_:hello,然后向其发布信息以此来达到交换信息的目的。如果有新的Sentinel加入,也会订阅_sentinel_:hello并发布消息。起到Sentinel感知Sentinel的作用。

7.4 Redis哨兵之实现原理

(3).每1秒ping

每个Sentinel每秒会对其他Sentinel和Redis执行ping命令做心跳检测,以此作为其是否存活的判断依据。

7.4 Redis哨兵之实现原理

2.主观下线和客观下线

(1).主观下线(偏见)

每个Sentinel节点会每隔1秒对主节点、从节点、其他Sentinel节点发送ping命令做心跳检测,当这些节点超过配置的down-after-milliseconds时间而未进行有效回复,Sentinel节点就会认为该节点存在故障,这个行为叫做主观下线,其配置如下。

sentinel down-after-milliseconds  mymaster 30000      

(2).客观下线(共识)

当Sentinel主观下线的节点是主节点时,该Sentinel节点会通过sentinel is-master-down-by-addr命令向其他Sentinel节点询问对主节点的判断,当超过quorum个数时,Sentinel节点认为主节点确实有问题,这时该Sentinel节点会做出客观下线的决定,即是大部分Sentinel节点都对主节点的下线做了同意的判定,这就是客观下线,其配置如下。

#sentinel monitor <masterName> <ip> <port> <quorum>
sentinel monitor mymaster 127.0.0.1 7000 2

#sentinel is-master-down-by-addr <ip> <port> <current_epoch> <runid>
sentinel is-master-down-by-addr 127.0.0.1 6379 0 *      
  • ip:主节点IP
  • port:主节点端口。
  • current_epoch:当前配置纪元。
  • runid:此参数有两种类型,不同类型决定了此API作用的不同。当runid等于“*”时,作用是Sentinel节点直接交换对主节点下线的判定。

    当runid等于当前Sentinel节点的runid时,作用是当前Sentinel节点希望目标Sentinel节点同意自己成为领导者的请求。

如sentinel-1节点对主节点做主观下线后,会向其余Sentinel节点(如sentinel-2和sentinel-3 节点)发送命令sentinel is-master-down-by-addr 127.0.0.1 6379 0 *,来询问它们的看法,返回结果包含如下三个参数。

  • down_state:目标Sentinel节点对于主节点的下线判断,1是下线,0是在线。
  • leader_runid:当leader_runid等于“*”时,代表返回结果是用来做主节点是否不可达的。当leader_runid等于具体的runid,代表目标节点统一runid称为领导者。
  • leader_epoch:领导者纪元。

3.领导者选举

(1).简介

  • 原因:只需要一个Sentinel节点完成故障转移
  • 方式:通过Sentinel的is-master-down-by-addr命令来竞选领导者

(2).流程

  • 每个做完主观下线的Sentinel节点向其他Sentinel节点发送is-master-down-by-addr命令,要求将自己设置为领导者。
  • 收到命令的Sentinel节点,如果没有同意过其他Sentinel节点发送的is-master-down-by-addr命令,将同意该请求,否则拒绝。
  • 如果该Sentinel节点发现自己的票数已经大于等于max(quorum,num(sentinels)/2+1),那么它将成为领导者。
  • 如果此过程没有选举出领导者,将等待一段时间重新进行选举。

(3).领导者选举示例

  • 假如Sentinel-1最先完成了主观下线,它会向Sentinel-2和Sentinel-3发送is-master-down-by-addr命令,Sentinel-2和Sentinel-3没有同意过其它节点,所以会同意选Sentinel-1为领导者。Sentinel-此时已经拿到2张投票,满足了大于等于max(quorum,num(sentinels)/2+1)=2的条件,所以此时Sentinel-1成为领导者。
  • 假如Sentinel-2接着完成了主观下线,由于每个Sentinel节点只有一票以及Sentinel-2和Sentinel-3把票投给了Sentinel-1,所以当Sentinel-2向Sentinel-1和Sentinel-3索要投票时,只能获取Sentinel-1的一票。
  • 最后,Sentinel-2接着完成了主观下线,由于Sentinel-2和Sentinel-3把票投给了Sentinel-1,Sentinel-1把票投给了Sentinel-2,所以Sentinel-3没有获得选票。
  • 从slave节点中选出一个“合适的”节点作为新的master节点。
  • 对上面的slave节点执行slaveof no one命令让其称为master节点。
  • 向剩余的slave节点发送切主命令,让他们称为新master节点的slave节点,复制规则和parallel-syncs参数有关。
  • 更新对原来master节点配置为slave,并保持着对其“关注”,当其恢复后命令它去复制新的master节点。
  • 选择slave-priority(slave节点优先级)最高的sqlave节点,如果存在则返回,不存在则继续。
  • 选择复制偏移量最大的slave节点(复制的最完整),如果存在则返回,不存在则继续。
  • 选择runid最小的从节点(最早的节点)。

继续阅读