理解哨兵机制原理

如果考虑使用阿里云Redis的话,哨兵是没有深入研究的价值的,因为阿里云Redis提供了自己的HA组件,来实现备份节点到主节点的转换。但是出于系统学习Redis知识的目的,我还是需要花点时间了解一下哨兵机制底层原理。

这篇笔记更多的是进行整理。

配置文件

我没有自己去配哨兵(我用的Helm,可以通过修改values.yaml文件实现哨兵机制)

  1. 两台Redis服务器的配置
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16

# 第一台
port 6379
masterauth admin
requirepass admin
protected-mode yes
bind 192.168.2.110

# 第二台
port 6380
masterauth admin
requirepass admin
protected-mode yes
bind 192.168.2.110
slaveof 192.168.2.110 6379

  1. 三个哨兵的配置
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31

# 第一个哨兵
port 26379
sentinel monitor mymaster 192.168.2.110 6379 2
sentinel auth-pass mymaster admin
sentinel down-after-milliseconds mymaster 15000
sentinel parallel-syncs mymaster 1
sentinel failover-timeout mymaster 80000
bind 192.168.2.110
protected-mode yes

# 第二个哨兵
port 26380
sentinel monitor mymaster 192.168.2.110 6379 2
sentinel auth-pass mymaster admin
sentinel down-after-milliseconds mymaster 15000
sentinel parallel-syncs mymaster 1
sentinel failover-timeout mymaster 80000
bind 192.168.2.110
protected-mode yes

# 第三个哨兵
port 26381
sentinel monitor mymaster 192.168.2.110 6379 2
sentinel auth-pass mymaster admin
sentinel down-after-milliseconds mymaster 15000
sentinel parallel-syncs mymaster 1
sentinel failover-timeout mymaster 80000
bind 192.168.2.110
protected-mode yes

工作原理

Sentinel与Sentinel之间、Sentinel与Redis之间的感知

  1. Sentinel与Redis节点:在Sentinel进程启动时,会与Master节点建立连接,然后Sentinel从Master节点获取所有节点信息,之后Sentinel会定时想Master节点和Slave节点发送info命令获取其拓步结构和状态信息。

  2. Sentinel与Sentinel节点:基于Redis的Pub/Sub功能,每个Sentinel会向sentinel:hello频道上发送该Sentinel对于主节点的判断以及当前Sentinel节点的信息;同时每个Sentinel也会订阅该频道,来获取其他Sentinel节点的信息已经它们对主节点的判断(主节点如果挂了,这个判断信息有个毛用啊)。

通过以上两步,所有的Sentinel节点以及它们与所有的Redis节点之间都已经彼此感知到,之后每个Sentinel节点会向主节点、从节点、以及其余Sentinel节点定时发送ping命令作为心跳检测,来确认这些节点是否可达。

判断Master节点是否可达

  1. 每个sentinel哨兵节点每隔1s向所有的master、slave以及其他sentinel节点发送一个PING命令,作用是通过心跳检测,检测主从服务器的网络连接状态

  2. 如果master节点回复PING命令的时间超过down-after-milliseconds设定的阈值(默认30s),则这个master会被sentinel标记为主观下线,修改其flags状态为SRI_S_DOWN

  3. 当sentinel哨兵节点将master标记为主观下线后,会向其余所有的sentinel发送sentinel is-master-down-by-addr消息,询问其他sentinel是否同意该master下线

  4. 每个sentinel收到命令之后,会根据发送过来的ip和port检查自己判断的结果,回复自己是否认为该master节点已经下线了

  5. sentinel收到回复之后,如果同意master节点进入主观下线的sentinel数量大于等于quorum,则master会被标记为客观下线,即认为该节点已经不可用。

  6. 在一般情况下,每个Sentinel每隔10s向所有的Master,Slave发送INFO命令。当Master被Sentinel标记为客观下线时,Sentinel向下线的Master的所有Slave发送INFO命令的频率会从10秒一次改为每秒一次。作用:发现最新的集群拓扑结构

基于Raft算法选举负责故障转移的Sentinel

  1. 判断客观下线的sentinel节点向其他sentinel节点发送SENTINEL is-master-down-by-addr ip port current_epoch runid

  2. 目标sentinel回复是否同意master下线并选举领头sentinel,选择领头sentinel的过程符合先到先得的原则。举例:sentinel1判断了客观下线,向sentinel2发送了第一步中的命令,sentinel2回复了sentinel1,说选你为领头,这时候sentinel3也向sentinel2发送第一步的命令,sentinel2会直接拒绝回复。

  3. 当sentinel发现选自己的节点个数超过majority的个数的时候,自己就是领头节点

  4. 如果没有一个sentinel达到了majority的数量,等一段时间,重新选举

故障转移

  1. 在进行选择之前需要先剔除掉一些不满足条件的slaver,这些slaver不会作为变成master的备选

    • 剔除列表中已经下线的从服务
    • 剔除有5s没有回复sentinel的info命令的slave
    • 剔除与已经下线的主服务连接断开时间超过down-after-milliseconds * 10 + master宕机时长的slaver
  2. 选主过程

    • 选择优先级最高的节点,通过sentinel配置文件中的replica-priority配置项,这个参数越小,表示优先级越高
    • 如果第一步中的优先级相同,选择offset最大的,offset表示主节点向从节点同步数据的偏移量,越大表示同步的数据越多
    • 如果第二步offset也相同,选择run id较小的

修改被选举出来的主节点的配置

  1. 领头sentinel会对选出来的从节点执行slaveof no one 命令让其成为主节点
  2. 领头sentinel向别的slave发送slaveof命令,告诉他们新的master是谁谁谁,你们向这个master复制数据
  3. 如果之前的master重新上线时,领头sentinel同样会给起发送slaveof命令,将其变成从节点

参考资料

  1. Redis哨兵机制原理详解
  2. SpringBoot2.0整合Redis高可用之Sentinel哨兵