Redis Sentinel 原理


  Sentinel 出现的前提背景

  Redis持久化机制和Redis主从架构相辅相成实现了Redis的数据高可用性以及服务的可扩展性和负载性,但是只依靠持久化方案和主从复制能力(负载和数据的冗余),再出现服务宕机的时候,故障切换无法自动去实现,还需要手工,这对人工成本造成了巨大的损失以及不稳定性。

  持久化+主从复制 仍存在的痛点

  使用主从复制,当 主服务器下线后无法恢复服务,在master节点下线后,只能手动将slave节点切换为master,但是不能自动完成故障转移。

  Sentinel的加入

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

  主从持久化机制与加入哨兵之后的对比:

 

 

   Sentinel的主要功能

  Redis Sentinel为Redis提供了完整的高可用解决方案。实际上这意味着使用Sentinel可以部署一套Redis,在没有人为干预的情况下去应付各种各样的失败事件。同时提供了一些其他的功能,例如:监控、通知、并为client提供配置。

  Sentinel的概念定义

  Redis-Sentinel是Redis官方推荐的高可用性(HA)解决方案,当用Redis做Master-slave的高可用方案时,假如master宕机了,Redis本身(包括它的很多客户端)都没有实现自动进行主备切换,而Redis-sentinel本身也是一个独立运行的进程,他能监控多个master-slave集群,发现master宕机后能进行自动切换。

  Sentinel的功能分布

  监控(Monitoring):Sentinel会不断的检查你的主节点和从节点是否正常工作。

  通知(Notification):被监控的Redis实例如果出现问题,Sentinel可以通过API (pub)通知系统管理员或者其他程序。

  自动故障转移(Automatic failover):如果一个主节点没有按照预期工作,Sentinel会开始进行故障转移,把一个节点提升为主节点,并重新配置其他的从节点使用新的主节点,其他的从节点会开始复制新的主节点,并且使用Redis服务的应用程序在连接的时候也被通知新的地址。

  配置提供(Configuration provider): 客户端可以把Sentinel作为权威的配置发布者来获得最新master地址,如果发生了故障转移,Sentinel集群会通知客户端新的master地址,并刷新Redis的配置。(Sentinel会返回最新的master地址)

  Sentinel的分布特性

 

   如果只使用单个sentinel进程来监控redis集群是不可靠的,当sentinel进程宕掉后(sentinel本身也有单点故障问题,single-point-of-failure)整个集群系统将无法按照预期的方式运行,所以有必要将Sentinel集群。

  Redis Sentinel 是一个分布式系统,Sentinel运行在有许多Sentinel进程互相合作的环境下,它本身就是这样被设计的。有许多Sentinel进程互相合作的优点如下:当多个Sentinel同意一个master不再可用的时候,就执行故障检测。降低了错误概率,即使并非全部的sentinel都在工作,sentinel也可以正常工作。

  分布方式总体如下图所示:

 

 

   哨兵模式的搭建:

  1. 配置sentinel.conf文件,配件需要监听的主从的master节点
    sentinel monitor <master-name> <ip> <redis-port> <quorum>
    master-name: 主节点master的名字
    quorum:哨兵集群中多少个sentinel认为master失效才下判定为客观下线,一般配置节点数/2+1,也就是说大于半数
  2. 如果主从master设置了密码,还需要配置:
    sentinel auth-pass <master-name> <password>

    由于master挂了之后,哨兵会进行重新选举,如果slave也配置了连接密码,那么最好在其他得节点配置上masterauth xxx,保障挂了得服务重启之后能正常加入主从中去。

  3. 修改心跳检测得主观下线时间
    sentinel down-after-milliseconds <master-name> <time>
    time:主观下线阈值,单位为毫秒ms
  4. 从服务器的个数配置
    sentinel parallel-psync mymaster 2
  5. 启动指定的哨兵配置文件启动哨兵
    ./redis-server sentinel.conf --sentinel &
  6. 查看状态信息
    配置完之后,进入./redis-cli,输入info命令,查看哨兵的状态信息|

    再使用同样的配置文件,启动另外两个哨兵,在查看信息之后发现哨兵数量变成了3个

  7. Java客户端连接哨兵模式,只需要配置哨兵节点即可

    spring.redis.sentinel.master=mymaster #哨兵配置中集群名字 
    spring.redis.sentinel.nodes=哨兵ip1:哨兵端口1,哨兵ip2:哨兵端口2,哨兵ip3:哨兵端口3

  哨兵模式的工作原理:  

  哨兵是一个分布式系统,可以在一个架构中运行多个哨兵进程,这些进程使用流言(gossip)协议来传播Master是否下线的信息,并使用投票协议来决定是否进行自动故障迁移,以及选择哪个slave作为新的Master。哨兵模式的具体工作原理如下:

  1、心跳机制:

  (1)Sentinel 与 Redis Node:Redis Sentinel 是一个特殊的 Redis 节点。在哨兵模式创建时,需要通过配置指定 Sentinel 与 Redis Master Node 之间的关系,然后 Sentinel 会从主节点上获取所有从节点的信息,之后 Sentinel 会定时向主节点和从节点发送info 命令获取其拓扑结构和状态信息。

  (2)Sentinel 与 Sentinel:基于 Redis 的订阅发布功能,每个 Sentinel 节点会向主节点的 Sentinel:hello 频道上发送该 Sentinel 节点对于主节点的判断以及当前Sentinel节点的信息,同时Sentinel节点也会订阅该频道,来获取其他Sentinel节点的信息以及他们对主节点的判断

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

  2、判断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下线

发送命令:sentinel is-master-down-by-addr <ip> <port> <current_epoch> <runid>

ip:主观下线的服务ip

port:主观下线的服务端口

current_epoch:sentinel的纪元

runid:*表示检测服务下线状态,如果是sentinel的运行id,表示用来选举领头sentinel

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

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

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

  3、基于Raft算法选举领头sentinel

  到现在为止,已经知道了master客观下线,那就需要一个sentinel来负责故障转移,那到底是哪个sentinel节点来做这件事?需要通过选举来实现,具体的选举过程如下:

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

    注:这时的runid是自己的run id,每个sentinel节点都有一个自己运行时id

  (2)目标sentinel回复是否同意master下线并选举领头sentinel,选择领头sentinel的过程符合先到先得的原则。

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

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

  4、故障转移

  有了领头sentinel之后,下面就进行故障转移,故障转移的一个主要问题和选择领头sentinel问题差不多,到底要选择哪一个slaver节点来作为master,哨兵模式有自己的选择判断。如下

  (1)在进行选择之前需要先剥除掉一些不满足条件的slaver,这些slaver不会作为master的备选。

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

  (2)选主过程

  a.选择优先级最高的节点,通过sentinel配置文件中的replica-priority配置项,这个参数越小,表示优先级越高

  b.如果第一步中的优先级相同,选择offset最大的,offset表示主节点向从节点同步数据的偏移量,越大表示同步的数据越多

  c.如果第二部offset也相同,选择runid较小的,runid越小说明启动时间越早

  5、修改配置:

  新的master节点选择出来之后,还需要做一些事情配置的修改,如下:

  (1)领头sentinel会对选出来的从节点执行slaveof no one 命令让其成为主节点

  (2)领头sentinel 向别的slaveof发送命令,告诉他们新的master是哪个,让这些节点向这个master复制数据

  (3)如果之前的master重新上线时,领头sentinel同样会发起slaveof命令,将其变成从节点

  Reids存在的问题:

  • 一旦主节点宕机,从节点晋升成主节点,同时需要修改应用方的主节点地址,还需要命令所有从节点去复制新的主节点,整个过程需要人工干预。[哨兵已解决] 

  • 节点的写能力受到单机的限制。[集群已解决] 

  • 节点的存储能力受到单机的限制。[集群已解决] 

  sentinel就介绍到这里,后面还会出一篇文章来介绍Redis 集群,说阐述它是怎么解决上述问题的。

 

posted @ 2022-12-27 17:04  梅晓煜  阅读(274)  评论(0)    收藏  举报