Redis哨兵机制原理

1.概述

Redis Sentinel是一个分布式系统,为Redis提供高可用性解决方案。能够在一个架构中运行多个 Sentinel 进程(progress), 这些进程使用流言协议(gossip protocols)来 接收关于主服务器是否下线的信息, 并使用投票协议(agreement protocols)来决定是否执行自动故 障迁移, 以及选择哪一个从服务器做为新的主服务器。html

Redis 的 Sentinel 系统用于管理多个 Redis 服务器(instance) 该系统执行如下三个任务:redis

  • 监控(Monitoring): Sentinel 会不断地按期检查你的主服务器和从服务器是否运做正常。
  • 提醒(Notification): 当被监控的某个 Redis 服务器出现问题时, Sentinel 能够经过 API 向管理员或者其余应用程序发送通知。
  • 自动故障迁移(Automaticfailover): 当一个主服务器不能正常工做时, Sentinel 会开始一次自动故障迁移操做, 它会将失效主服务器的其中 一个从服务器升级为新的主服务器, 并让失效主服务器的其余从服务器改成复制新的主服务器; 当客 户端试图链接失效的主服务器时, 集群也会向客户端返回新主服务器的地址, 使得集群可使用新主 服务器代替失效服务器。

2.Sentinel 工做原理分析

(1)哨兵文件详解

 配置一:sentinel monitor <master-name> <ip> <port> <quorum>数据库

 这个配置表达的是 哨兵节点按期监控 名字叫作 <master-name>  而且 IP 为 <ip> 端口号为 <port> 的主节点。<quorum> 表示的是哨兵判断主节点是否发生故障的票数。也就是说若是咱们将<quorum>设置为2就表明至少要有两个哨兵认为主节点故障了,才算这个主节点是客观下线的了,通常是设置为sentinel节点数的一半加一。数组

配置二:sentinel down-after-milliseconds <master-name> <times>服务器

 每一个哨兵节点会按期发送ping命令来判断Redis节点和其他的哨兵节点是不是可达的,若是超过了配置的<times>时间没有收到pong回复,就主观判断节点是不可达的,<times>的单位为毫秒。网络

配置三:sentinel parallel-syncs <master-name> <nums>数据结构

 当哨兵节点都认为主节点故障时,哨兵投票选出的leader会进行故障转移,选出新的主节点,原来的从节点们会向新的主节点发起复制,这个配置就是控制在故障转移以后,每次能够向新的主节点发起复制的节点的个数,最多为<nums>个,由于若是不加控制会对主节点的网络和磁盘IO资源很大的开销。架构

配置四:sentinel failover-timeout <master-name>  <times>分布式

 这个表明哨兵进行故障转移时若是超过了配置的<times>时间就表示故障转移超时失败。spa

配置五: sentinel auth-pass <master-name> <password>

 若是主节点设置了密码,则须要这个配置,不然哨兵没法对主节点进行监控。

(2)为何要用到哨兵

哨兵(Sentinel)主要是为了解决在主从复制架构中出现宕机的状况,主要分为两种状况:

1).从Redis宕机

这个相对而言比较简单,在Redis中从库从新启动后会自动加入到主从架构中,自动完成同步数据。在Redis2.8版本后,主从断线后恢复
的状况下实现增量复制。

2).主Redis宕机

这个相对而言就会复杂一些,须要如下2步才能完成
a. 在从数据库中执行SLAVEOF NO ONE命令,断开主从关系而且提高为主库继续服务
b. 第二步,将主库从新启动后,执行SLAVEOF命令,将其设置为其余库的从库,这时数据就能更新回来

因为这个手动完成恢复的过程实际上是比较麻烦的而且容易出错,因此Redis提供的哨兵(sentinel)的功能来解决

(3)哨兵机制(sentinel)的高可用

Sentinel(哨兵)是Redis 的高可用性解决方案:由一个或多个Sentinel 实例 组成的Sentinel 系统能够监视任意多个主服务器,以及这些主服务器属下的全部从服务器,并在被监视的主服务器进入下线状态时,自动将下线主服务器属下的某个从服务器升级为新的主服务器。

如图所示

在Server1 掉线后:

 

升级Server2 为新的主服务器:

(4)哨兵的定时监控

任务1:每一个哨兵节点每10秒会向主节点和从节点发送info命令获取最拓扑结构图,哨兵配置时只要配置对主节点的监控便可,经过向主节点发送info,获取从节点的信息,并当有新的从节点加入时能够立刻感知到

任务2:每一个哨兵节点每隔2秒会向redis数据节点的指定频道上发送该哨兵节点对于主节点的判断以及当前哨兵节点的信息,同时每一个哨兵节点也会订阅该频道,来了解其它哨兵节点的信息及对主节点的判断,其实就是经过消息publish和subscribe来完成的

任务3:每隔1秒每一个哨兵会向主节点、从节点及其他哨兵节点发送一次ping命令作一次心跳检测,这个也是哨兵用来判断节点是否正常的重要依据

主观下线:所谓主观下线,就是单个sentinel认为某个服务下线(有多是接收不到订阅,之间的网络不通等等缘由)。

 

sentinel会以每秒一次的频率向全部与其创建了命令链接的实例(master,从服务,其余sentinel)发ping命令,经过判断ping回复是有效回复,仍是无效回复来判断实例时候在线(对该sentinel来讲是“主观在线”)。

 

sentinel配置文件中的down-after-milliseconds设置了判断主观下线的时间长度,若是实例在down-after-milliseconds毫秒内,返回的都是无效回复,那么sentinel回认为该实例已(主观)下线,修改其flags状态为SRI_S_DOWN。若是多个sentinel监视一个服务,有可能存在多个sentinel的down-after-milliseconds配置不一样,这个在实际生产中要注意。

客观下线:当主观下线的节点是主节点时,此时该哨兵3节点会经过指令sentinel is-masterdown-by-addr寻求其它哨兵节点对主节点的判断,若是其余的哨兵也认为主节点主观线下了,则当认为主观下线的票数超过了quorum(选举)个数,此时哨兵节点则认为该主节点确实有问题,这样就客观下线了,大部分哨兵节点都赞成下线操做,也就说是客观下线

 (5)哨兵lerder选举流程

若是主节点被断定为客观下线以后,就要选取一个哨兵节点来完成后面的故障转移工做,选举出一个leader的流程以下:

a)每一个在线的哨兵节点均可以成为领导者,当它确认(好比哨兵3)主节点下线时,会向其它哨兵发is-master-down-by-addr命令,征求判断并要求将本身设置为领导者,由领导者处理故障转移;
b)当其它哨兵收到此命令时,能够赞成或者拒绝它成为领导者;
c)若是哨兵3发现本身在选举的票数大于等于num(sentinels)/2+1时,将成为领导者,若是没有超过,继续选举…………

(6)自动故障转移机制

在从节点中选择新的主节点

sentinel状态数据结构中保存了主服务的全部从服务信息,领头sentinel按照以下的规则从从服务列表中挑选出新的主服务

  1. 过滤掉主观下线的节点 
  2. 选择slave-priority最高的节点,若是由则返回没有就继续选择
  3. 选择出复制偏移量最大的系节点,由于复制便宜量越大则数据复制的越完整,若是由就返回了,没有就继续
  4. 选择run_id最小的节点

更新主从状态

经过slaveof no one命令,让选出来的从节点成为主节点;并经过slaveof命令让其余节点成为其从节点。

 将已下线的主节点设置成新的主节点的从节点,当其回复正常时,复制新的主节点,变成新的主节点的从节点

同理,当已下线的服务从新上线时,sentinel会向其发送slaveof命令,让其成为新主的从

 3.Sentinel获取服务器信息

(1) Sentinel获取主服务器信息

    Sentinel默认会以每10秒一次的频率,经过命令链接向主服务器发送info命令,经过分析info命令的回复来获取主服务器的当前信息,就像在上篇讲到的复制功能,在客户端输入info replication 命令同样,Sentinel能够获取如下两方面的信息:

    (1) 关于主服务器自己的信息,包括服务器run_id,role的服务器角色。

    (2) 关于全部从服务器的信息,每一个从服务器都由一个slave字符串开头的行记录,记录了从服务器IP和端口(主服务器中有从库的配置信息)。

(2)Sentinel获取从服务器信息

    当Sentinel发现主服务器有新的从服务器出现时,Sentinel除了会为这个新的从服务器建立相应的实例结构(sentinelRedisInstance)以外,Sentinel还会建立链接到从服务器的命令链接和订阅链接。Sentinel默认会以每10秒一次的频率经过命令链接从服务器发送info命令,经过分析info命令的回复来获取从服务器的当前信息。包括:从服务器运行run_ID、从服务器角色role、主服务器的ip及端口、主从服务器的链接状态master_link_status、从服务器的优先级slave_priority。

 (3)Sentinel向主从服务器发送信息

     在默认状况下, Sentinel会以每2秒一次的频率,经过命令链接向全部被监视的主服务器和从服务器发送如下格式的命令:

  

    这条命令向服务器的_sentinel_:hello频道发送了一条信息,信息的内容由多个参数组成:

    (1) 以s_开头以参数记录的是sentinel自己的信息。

    (2) 而m_开头的参数记录的则是主服务器的信息,若是sentinel正在监视的是主服务器,那么这些参数就是主服务器的信息,若是sentinel正在监视的是从服务器,那么这些参数记录就是从服务器正在复制的主服务器的信息。

 

参数 描述
S_ip Sentinel的ip地址
S_port Sentinel的端口号
S_runid Sentinel的运行ID

S_epoch

Sentinel 的当前配置纪元

m_name 主服务器的名字
M_ip 主服务器的IP地址
M_port 主服务器的端口号
M_epoch 主服务器的当前配置纪元

 

    

如下是一条sentinel经过publish命令向主服务器发送的信息示例:

 

  

这个示例中sentinel的ip地址为172.0.0.1端口号为26379, 运行ID为后面一串,当前纪元为0。主服务器的名字为mymaster,ip地址为127.0.0.1,端口号为6379, 当前纪元为0。

 (4)sentinel接收来自主服务器和从服务器的频道信息

    当sentinel与一个主服务器或者从服务器创建起订阅链接以后,Sentinel就会经过订阅链接,向服务器发送如下命令:subscribe_sentinel_:hello 。对于每一个与Sentinel链接的服务器,Sentinel既经过命令连向服务器的_sentinel_:hello频道发送信息,又经过订阅链接从服务器的_sentinel_:hello频道接收信息。

    当有三个sentinel,分别是sentinel一、sentinel2 、sentinel3。三个sentinel在监视同一个服务器,那么当sentinel1向服务器的_sentinel_:hello频道发送一条信息时,全部订阅了_sentinel_:hello频道的sentinel(包括sentinel1本身在内)都会收到这条信息。

    当一个sentinel从_sentinel_:hello频道收到一条信息时,sentinel会对这条信息进行分析,提取出信息中sentinel 的 ip 、port、runID等8个参数,并进行如下检查:

    (1) 若是信息中记录的sentinel运行ID和接收信息的sentinel运行ID相同,那么说明这条信息是sentinel本身发送的,sentinel将丢弃这条信息,不作进一步处理。

    (2) 相反地,若是信息中记录的sentinel运行ID和接收信息的sentinel运行ID不相同,那说明这条信息监视同一个服务器的其它sentinel发来的,接收信息的sentinel将根据信息中的参数,对相应主服务器的实例结构进行更新。

 (5)sentinel更新本身的sentinels字典

    sentinel为主服务器建立实例结构中的sentinels字典,保存了sentinel自己,还监视这个主服务器的其余sentinel的资料。当一个sentinel接收到其余sentinels发来的信息时,接收的sentinel会从信息中分析并提取出两方面参数:

    (1)与sentinel有关的参数,包括sentinel的ip、port、runid、配置纪元。

    (2)与主服务器有关的参数, 包括监视主服务器的ip、port、runid、配置纪元。

    假设分别有三个sentinel: 127.0.0.1:2637九、127.0.0.1:26380、127.0.0.1:26381。三个sentinel正在监视主服务器127.0.0.1:6379, 那么当127.0.0.1:26379这个sentinel接收到如下消息时:

    

    这个sentinel将执行如下动做:

    (1) 第一条信息发送者为本身,信息忽略。

    (2) 第二条信息发送者为26381, sentinel会根据信息提取出内容,对sentinels字典中26381对应的实例结构进行更新。

    (3) 第三条信息发送者为23680,一样更新字典中的23680对应的实例结构。

    每一个sentinel都有本身的一个sentinels字典, 对于26379的sentinel它的sentinels字典信息保存了26380和26381两个sentinel信息。其它sentinel也同样。

 (6)sentinel建立连向其余sentinel的命令链接

    当sentinel经过频道信息发现一个新的sentinel时,不只更新sentinels字典,还会建立一个连向sentinel命令链接,而新的sentinel也会建立连向这个sentinel的命令链接,最终监视同一个主服务器的多个sentinel将造成相互链接的网络。以下图所示:

 

 4.Sentinel的工做原理总结

 1):每一个Sentinel以每秒钟一次的频率向它所知的Master,Slave以及其余 Sentinel 实例发送一个 PING 命令。

 2):若是一个实例(instance)距离最后一次有效回复 PING 命令的时间超过 down-after-milliseconds 选项所指定的值, 则这个实例会被 Sentinel 标记为主观下线。 

 3):若是一个Master被标记为主观下线,则正在监视这个Master的全部 Sentinel 要以每秒一次的频率确认Master的确进入了主观下线状态。 

 4):当有足够数量的 Sentinel(大于等于配置文件指定的值)在指定的时间范围内确认Master的确进入了主观下线状态, 则Master会被标记为客观下线 。

 5):在通常状况下, 每一个 Sentinel 会以每 10 秒一次的频率向它已知的全部Master,Slave发送 INFO 命令 。

 6):当Master被 Sentinel 标记为客观下线时,Sentinel 向下线的 Master 的全部 Slave 发送 INFO 命令的频率会从 10 秒一次改成每秒一次 。

 7):若没有足够数量的 Sentinel 赞成 Master 已经下线, Master 的客观下线状态就会被移除。 

 若 Master 从新向 Sentinel 的 PING 命令返回有效回复, Master 的主观下线状态就会被移除。

 5.参考资料

https://blog.csdn.net/nuomizhende45/article/details/82831966

https://my.oschina.net/u/172871/blog/596976

https://www.cnblogs.com/qinghe123/p/9547884.html

https://www.cnblogs.com/jaycekon/p/6237562.html

https://blog.csdn.net/RobertoHuang/article/details/70768922

https://www.cnblogs.com/leeSmall/p/8398401.html

https://blog.csdn.net/u012240455/article/details/81843714

https://www.cnblogs.com/MrHSR/p/10119843.html

相关文章
相关标签/搜索