哨兵相当于额外的一层监控,而不是与 Redis 服务交织在一起。
在主从模式下(主从模式就是把上图的所有哨兵去掉),master节点负责写请求,然后异步同步给slave节点,从节点负责处理读请求。如果master宕机了,需要手动将从节点晋升为主节点,并且还要切换客户端的连接数据源。这就无法达到高可用,而通过哨兵模式就可以解决这一问题。
Sentinel模式是Redis的高可用方式,哨兵节点是特殊的Redis服务,主要用来监控Redis实例节点。哨兵架构下Client端第一次从哨兵找出Redis的主节点,后续就直接访问Redis的主节点,不会每次都通过Sentinel访问Redis的主节点,当Redis的主节点挂掉时,哨兵会第一时间感知到,并且在Slave节点中重新选出来一个新的Master,然后将新的Master信息通知给Client端,从而实现高可用。这里面Redis的Client端一般都实现了订阅功能,订阅Sentinel发布的节点变动消息。
监控
:哨兵会不断地检查你的Master和Slave是否运作正常。
提醒
:当被监控的某个Redis节点出现问题时,哨兵可以通过 API 向管理员或者其他应用程序发送通知。
自动故障迁移
:当一个Master不能正常工作时,哨兵会进行自动故障迁移操作,将失效Master的其中一个Slave升级为新的Master,并让失效Master的其他Slave改为复制新的Master;当客户端试图连接失效的Master时,集群也会向客户端返回新Master的地址,使得集群可以使用新Master代替失效Master。
1、配置sentinel.conf文件,配件需要监听的主从的master节点
sentinel monitor <master‐name> <ip> <redis‐port> <quorum>
(1)master‐name:主节点master的名字
(2)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>
4、从服务器的个数配置:
sentinel parallel-syncs 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 protocols)来传播Master是否下线的信息,并使用投票协议(agreement protocols)来决定是否执行自动故障迁移,以及选择哪个Slave作为新的Master。哨兵模式的具体工作原理如下:
(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 命令作为心跳检测, 来确认这些节点是否可达。
(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节点已经下线了
回复内容主要包含三个参数(由于上面发送的runid参数是*,这里先忽略后两个参数)
down_state(1表示已下线,0表示未下线)
leader_runid(领头sentinal id)
leader_epoch(领头sentinel纪元)。
(5)sentinel收到回复之后,如果同意master节点进入主观下线的sentinel数量大于等于quorum,则master会被标记为客观下线,即认为该节点已经不可用。
(6)在一般情况下,每个 Sentinel 每隔 10s 向所有的Master,Slave发送 INFO 命令。当Master 被 Sentinel 标记为客观下线时,Sentinel 向下线的 Master 的所有 Slave 发送 INFO 命令的频率会从 10 秒一次改为每秒一次。作用:发现最新的集群拓扑结构
到现在为止,已经知道了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的过程符合先到先得的原则。举例:sentinel1判断了客观下线,向sentinel2发送了第一步中的命令,sentinel2回复了sentinel1,说选你为领头,这时候sentinel3也向sentinel2发送第一步的命令,sentinel2会直接拒绝回复
(3)当sentinel发现选自己的节点个数超过 majority 的个数的时候,自己就是领头节点
(4)如果没有一个sentinel达到了majority的数量,等一段时间,重新选举
有了领头sentinel之后,下面就是要做故障转移了,故障转移的一个主要问题和选择领头sentinel问题差不多,到底要选择哪一个slaver节点来作为master呢?按照我们一般的常识,我们会认为哪个slave节点中的数据和master中的数据相识度高哪个slaver就是master了,其实哨兵模式也差不多是这样判断的,不过还有别的判断条件,详细介绍如下:
(1)在进行选择之前需要先剔除掉一些不满足条件的slaver,这些slaver不会作为变成master的备选
(2)选主过程:
新的master节点选择出来之后,还需要做一些事情配置的修改,如下: