Back
详情
Redis——详解redis哨兵模式运作原理以及优缺点

什么是哨兵模式

Sentinel 的主要作⽤其实就是检测主、从节点的健康状态,并在 Master 出现故障的时候完成⾃动选主、切主流程。同时了为了使得 Sentinel 在选举 Leader 过程达成共识,Sentinel 之间通过 Raft 共识协议进⾏通信

Redis Sentinel同时提供了一些其他的功能,例如:监控、通知、并为client提供配置。
下面是Sentinel的功能列表:

  • 监控(Monitoring):Sentinel不断的去检查你的主从实例是否按照预期在工作。
  • 通知(Notification):Sentinel可以通过一个api来通知系统管理员或者另外的应用程序,被监控的Redis实例有一些问题。
  • 自动故障转移(Automatic failover):如果一个主节点没有按照预期工作,Sentinel会开始故障转移过程,把一个从节点提升为主节点,并重新配置其他的从节点使用新的主节点,使用Redis服务的应用程序在连接的时候也被通知新的地址。
  • 配置提供者(Configuration provider):Sentinel给客户端的服务发现提供来源:对于一个给定的服务,客户端连接到Sentinels来寻找当前主节点的地址。当故障转移发生的时候,Sentinels将报告新的地址。

Sentinel的分布式特性

Redis Sentinel是一个分布式系统,Sentinel运行在有许多Sentinel进程互相合作的环境下,它本身就是这样被设计的。有许多Sentinel进程互相合作的优点如下:

  1. 当多个Sentinel同意一个master不再可用的时候,就执行故障检测。这明显降低了错误概率
  2. 即使并非全部的Sentinel都在工作,Sentinel也可以正常工作,这种特性,让系统非常的健康。

所有的Sentinels,Redis实例,连接到Sentinel和Redis的客户端,本身就是一个有着特殊性质的大型分布式系统。本文将逐步地介绍这些概念,最开始是一些基本的信息来理解Sentinel的基本属性,后面是更复杂的信息来理解Sentinel是怎么工作的。

Sentinel配置以及参数

在Sentinel配置文件sentinel.conf中,只需要制定要监控的主节点,并给每个单独的主节点一个不同的名称。不需要指定从节点,从节点会被自动发现
在故障转移中每当一个从节点被提升为主节点或者当一个新的Sentinel被发现的时候,配置信息也被重新写入。

示例

sentinel monitor mymaster 127.0.0.1 6379 2
sentinel down-after-milliseconds mymaster 60000
sentinel failover-timeout mymaster 180000
sentinel parallel-syncs mymaster 1

sentinel monitor resque 192.168.1.3 6380 4
sentinel down-after-milliseconds resque 10000
sentinel failover-timeout resque 180000
sentinel parallel-syncs resque 5

配置Sentinel的注意事项

  1. 一个健康的集群部署,至少需要三个Sentinel实例
  2. 三个Sentinel实例应该被放在互相隔离的电脑上或虚拟机中,比如说不同的物理机或者在不同的可用区域上执行的虚拟机。
  3. Sentinel + Redis 分布式系统在失败期间并不确保写入请求被保存,因为Redis使用异步拷贝。可是有很多部署Sentinel的 方式来让窗口把丢失写入限制在特定的时刻,当然也有另外的不安全的方式来部署。
  4. 要经常测试:如果你在开发环境中没有经常测试,或者在生产环境中也没有,那就没有高可用的设置是安全的。你或许有一个错误的配置而仅仅只是在很晚的时候才出现(凌晨3点你的主节点宕掉了)。
  5. 小心网络地址转换表,端口映射:Sentinel,Docker ,其他的网络地址转换表,端口映射 使用应该很小心的使用:Docker执行端口重新映射,破坏Sentinel自动发现另外的Sentinel进程和一个主节点的从节点列表。在文章的稍后部分查看更过关于Sentinel和Docker的信息。

配置参数/选项

  • quorum 是 需要同意主节点不可用的Sentinels的数量
    • 然而quorum 仅仅只是用来检测失败。为了实际的执行故障转移,Sentinels中的一个需要被选定为leader并且被授权进行操作,这仅仅发生在大多数Sentinels进行投票的时候。
    • 比如如果你有五个Sentinel进程,对于一个主节点quorum被设置为2,下面是发生的事情:
      • 同时有两个Sentinels同意主节点不可用,其中的一个将会尝试开始故障转移。
      • 如果至少有三个Sentinels是可用的,故障转移将会被授权并且开始
  • down-after-milliseconds:当一个实例失去联系(要么不回复我们的请求,要么回复一个错误)超过了这个时间(毫秒为单位),Sentinel就开始认为这个实例挂掉了。
  • parallel-syncs:** parallel-syncs与故障转移之后从节点的复制有关:它规定了每次向新的主节点发起复制操作的从节点个数**。数量越少,完成故障转移过程将花费更多的时间,如果从节点为旧的数据提供服务,你或许不想所有的从节点使用主节点进行重新同步。复制进程对于从节点来说大部分是非阻塞的,还是有一个时刻它会停下来去从主节点加载数据。你或许想确保一次只有一个从节点是不可达的,可以通过设置这个选项的值为1来完成。

哨兵的监控功能

默认情况下,Sentinel 以每秒一次的频率向包括 Master、Slave、其他 Sentinel 在内的实例发送 PING 命令,如果 slave 没有在在规定时间内响应「哨兵」的 PING 命令,「哨兵」就认为该slave宕机了,就会将他记录为「(主观)下线状态」;

假如 master 没有在规定时间响应 「哨兵」的 PING 命令,哨兵就判定Master(主观)下线,开始执行「自动切换 master 掌门」的流程。

PING 命令的回复有两种情况

  • 有效回复:返回 +PONG、-LOADING、-MASTERDOWN 任何一种;
  • 无效回复:有效回复之外的回复,或者再指定时间内返回任何回复。

为了Master「假死」,「哨兵」设计了「主观下线」和「客观下线」两种状态。

主观下线与客观下线

  • 主观下线 SDOWN: 如果 监控的服务器节点 在 down-after-milliseconds设置的毫秒时效内没有响应检测,则会被判定为 主观下线;这个状态适用所有服务器节点
  • 客观下线 ODOWN: 主服务器节点在发生故障的时候,sentinel 会通过 is-master-down-by-addr 命令向其他 sentinel 节点询问 该主服务器节点的状态,如果超过 quorum 个数的哨兵节点都认为 主服务器节点不可达,则判定为客观下线;这个状态**只会针对 主服务器节点(**对于从服务器没有客观下线,从下面源码中能找到答案)

客观下线与主观下线与sentinel 关系其实也是redis和sentinel的交互

  1. 每个 sentinel 以 每秒一次 的频率,向它所知的 主服务器节点 和 从服务器节点 以及其他 sentinel节点 发送PING 命令,检测其状态
  2. 如果一个 节点 或者 实例 距离 最后一次 有效回复 PING 命令的时间超过 down-after-milliseconds设定的值,那么这个 节点 或者 实例会被 sentinel 标记为 SDOWN 主观下线
  3. 随后正在监控这个 主服务器节点 的所有 sentinel 都要以每秒一次的频率确认这个 主服务器节点 是否真正进入了 主观下线状态,一旦有 足够数量 的 sentinel 在指定时间范围内同意这个下线判断,那么这个 服务器就要被标记为** ODOWN 客观下线**,然后sentinel 向 客观下线主服务器 的所有 从服务器 发送 INFO 命令的频率,会从 10 秒一次改为 每秒一次。
  4. 当然,如果 中途当没有足够数量的 sentinel 同意下线判断,那这个 客观下线 状态就会被移除,而且当 主服务器重新对 PING进行有效响应的时候,那 主观下线状态就会被移除。
  5. 接上面,如果还是 客观下线状态,就需要进行 主服务器 选举逻辑

自动切换主库

「哨兵」的第二个任务是在master发生故障时需要按照一定规则选择新的master。根据规则给每个从节点(slave)打分。
如图所示:

选择新Master:筛选slave并计算各自权重(打分)

筛选条件

  • 从库当前在线状态,下线的直接丢弃
  • 评估之前的网络连接状态 down-after-milliseconds * 10:如果从库总是和主库断连,而且断连次数超出了一定的阈值(10 次),我们就有理由相信,这个从库的网络状况并不是太好,就可以把这个从库筛掉了

打分/权重计算

过滤掉不合适的 slave 之后,则进入打分环节。打分会按照三个规则进行三轮打分,规则分别为:

  • slave 优先级,通过 slave-priority 配置项,给不同的从库设置不同优先级(后台有人没办法),优先级高的直接晋级为新 master 掌门。
  • slave_repl_offset与 master_repl_offset进度差距,如果都一样,那就继续下一个规则。其实就是比较 slave 与旧 master 复制进度的差距;
  • slave runID,在优先级和复制进度都相同的情况下,ID 号最小的从库得分最高,会被选为新主库

通知

选定新的master过后,「哨兵」将新 「master 」的连接信息发送给其他 slave ,并且让 slave 执行 replacaof 命令,和新「master 」建立连接,并进行数据复制

哨兵集群的选举

判断完主库下线后,由哪个哨兵节点来执行主从切换呢?这里就需要哨兵集群的选举机制了

为什么需要进行选举

为了避免哨兵的单点情况发生,所以需要一个哨兵的分布式集群。
作为分布式集群,必然涉及共识问题(即选举问题);同时故障的转移和通知都只需要一个主的哨兵节点就可以了。

哨兵的选举机制?

哨兵的选举机制其实很简单,就是一个Raft选举算法: 选举的票数大于等于num(sentinels)/2+1时,将成为领导者,如果没有超过,继续选举Raft算法。
任何一个想成为 Leader 的哨兵,要满足两个条件: 、

  • 第一,拿到半数以上的赞成票;
  • 第二,拿到的票数同时还需要大于等于哨兵配置文件中的 quorum 值。以 3 个哨兵为例,假设此时的 quorum 设置为 2,那么,任何一个想成为 Leader 的哨兵只要拿到 2 张赞成票,就可以了。

除此之外,「哨兵」还需要将新Master的连接信息通知所有客户端,。