Redis Sentinel(哨兵)实现原理

Redis Sentinel是由三个定时任务、主管下线和客观下线还有Sentinel领导者选举和故障转移实现的。


  

  先来看看三个定时任务是哪三个


  1.每隔十秒,每个Sentinel(哨兵节点)会向主节点和从节点发送info命令获取最新的拓扑结构,那这个任务有什么用呢?

   a. 哨兵节点可以通过info命令从主节点获取从节点的信息,这也是为什么哨兵节点为什么只配置主节点不配置从节点的原因。

   b. 每当有新的节点加入时,哨兵节点可以立刻感知到,

   c. 当有节点崩了或者进行了故障转移,哨兵节点可以通过info命令实时更新相关节点的信息。


  2.每隔两秒,每个哨兵节点会向Redis 数据节点的_Sentinel_:hello频道通过发布\订阅的方式在该频道上发送该节点对主节点还有当前哨兵节点的信息,同时其他的哨兵节点也会订阅这个频道,用于了解其他的哨兵节点还有其他哨兵节点对主节点的判断,这个定时任务的具体功能可以分为两点,如下:

   a. 感知新加入的哨兵节点,通过订阅主节点的_sentinel_:hello可以了解其他哨兵节点的信息,如果是最新的加入的哨兵节点,就保存该节点的信息,并与其建立连接。

   b. 哨兵节点直接交换对主节点的判断,用于客观下线主观下线


  3.每隔一秒,每个哨兵节点会向主节点、从节点和其他的哨兵节点发送一条相当于心跳检测(就是定时给你发一条消息,你回复我了,就证明你还活着,你没回复我那说明你崩了)的ping命令,用于检测各个节点的可达性。通过这个定时任务可以让每个哨兵节点实时的监控其余的所有节点,这个定时任务是判断节点失败的关节所在。

  主观下线和客观下线

  
  这东西其实很好理解,举个例子,你病了,我一个人觉你生病了,这叫主观下线,我拿着我的观点和一群人一起讨论最后投票的结果是你生病了,这就是客观下线。

  上面每秒一次的定时任务,会每秒发送一个ping命令作为心跳检测,如果节点超过了一个自定义的时间(可以调整down-after-milliseconds参数来控制这个超时时间的大小)这个节点没有进行回复,那么发送心跳链接的哨兵节点就会对这个未回复的节点做失败判定,这个行为就是主观下线。很明显,这个主观下线是一个哨兵节点的判断,存在误判的可能

  当哨兵节点主观下线的是主节点的时候,该哨兵节点会通过一个sentinel is-master-dwon-addr命令来向询问其余的哨兵节点对这个节点的判断,当有一定数量(这个数量由quorum参数决定,比如将quorum参数设置为2,代表至少需要两个哨兵节点认为主节点不可达,才会做出客观下线,该参数设置的越小,那么客观下线的条件就越宽松,反之越严格,一般会设置为哨兵节点总数的一半加一,向上取整)的哨兵节点对该节点做出失败判断时,哨兵们会做出客观下线的决定。

  注:sentinel is-master-dwon-addr命令
    语法如下:
    sentinel is-master-dwon-by-addr <ip> <port> <current_epoch> <runid>

  ip:主节点的ip
  port:主节点的端口
  current_epoch:当前配置
  runid:这个参数有两中类型,当runid等于“*”的时候,是哨兵节点之间交换对主节点判定的时候使用的;当runid等于当前哨兵节点的runid时,作用时当前哨兵节点希望其他的哨兵节点同意自己成为领导者的请求

  注意:故障转移只会出现在客观下线后,主观下线没有后续的故障转移操作。

  
  
  

  Sentinel领导者选举

  故障转移时在客观下线后发生了,但是不是做出客观下线后立刻就进行故障转移,因为故障转移只需要一个哨兵节点来完成,所以哨兵节点之间会有一个领导者选举的工作,用来选出一个哨兵节点作为领导之进行故障转移的工作。Rdeis使用了Raft算法实现领导者选举,大致流程如下:
  
  1. 每个哨兵节点都有资格成为领导者,当它确认主节点主观下线时,会向其他哨兵节点发送sentinel is-master-dwon-addr命令,要求将自己设置为领导者。
  
  2. 收到该命令的哨兵节点,如果没有同意过其他哨兵节点的sentinel is-master-dwon-addr命令,将同意该请求,否则会拒绝。
  
  3.当该哨兵节点发现自己的票数大于等于max(quorum,num(哨兵节点的总数)/2+1)的时候,那么它将成为领导者。
  
  4.如果这次的过程中没有选举出领导者,将进入下一次选举。

  
  
  

  故障转移

  选取出领导者后,由成为了领导者的哨兵节点负责故障转移。转移的步骤如下:
  
  1.从节点里选取一个成为新的主节点。选择的方法如下:
  
   a. 过滤不健康(主观下线、断线)的节点、5秒内没有回复过哨兵节点ping命令的节点、与主节点失联超过down-after-milliseconds(超时时间)*10秒的节点。
  
   b. 选择slave-priority(从节点优先级)最高的从节点列表,如果存在就返回,不存在就进入下一步。
  
   c. 选择复制偏移量最大的从节点,也就是当前复制数据最多的从节点,如果存在就返回,不存在就进入下一步。
  
   d. 选择runid最小的从节点。
  
  
  2.领导者哨兵节点会对上一步选出的从节点执行slaveof no one(对从节点使用可以重置该节点的身份,Redis默认每个节点都是主节点)命令,让其成为主节点。
  
  
  3.领导者哨兵节点会对剩余的从节点发出命令,让它们成为新主节点的从节点。
  
  
  4.哨兵节点们会把原先做出失败判定的主节点的身份切换为从节点,并对其进行持续监控,当该节点恢复时命令它去复制新的主节点。
  

    先就写这么多了。

  以上内容主要来自《Redis开发与运维》。

  这本书同样很nice(不是广告),感兴趣的小伙伴可以去淘宝的新华书店购买。

  我发言完毕 bye~

猜你喜欢

转载自blog.csdn.net/imagineluopan/article/details/120807212