一、什么是哨兵模式:
1、哨兵模式的架构:
哨兵相当于额外的一层监控,而不是与 Redis 服务交织在一起。
2、什么是哨兵模式:
在主从模式下(主从模式就是把上图的所有哨兵去掉),master节点负责写请求,然后异步同步给slave节点,从节点负责处理读请求。如果master宕机了,需要手动将从节点晋升为主节点,并且还要切换客户端的连接数据源。这就无法达到高可用,而通过哨兵模式就可以解决这一问题。
Sentinel模式是Redis的高可用方式,哨兵节点是特殊的Redis服务,主要用来监控Redis实例节点。哨兵架构下Client端第一次从哨兵找出Redis的主节点,后续就直接访问Redis的主节点,不会每次都通过Sentinel访问Redis的主节点,当Redis的主节点挂掉时,哨兵会第一时间感知到,并且在Slave节点中重新选出来一个新的Master,然后将新的Master信息通知给Client端,从而实现高可用。这里面Redis的Client端一般都实现了订阅功能,订阅Sentinel发布的节点变动消息。
3、哨兵的主要工作任务:
监控
:哨兵会不断地检查你的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>
- time:主观下线阈值,单位为毫秒ms
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、心跳机制:
(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节点已经下线了
回复内容主要包含三个参数(由于上面发送的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 秒一次改为每秒一次。作用:发现最新的集群拓扑结构
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的过程符合先到先得的原则。举例:sentinel1判断了客观下线,向sentinel2发送了第一步中的命令,sentinel2回复了sentinel1,说选你为领头,这时候sentinel3也向sentinel2发送第一步的命令,sentinel2会直接拒绝回复
(3)当sentinel发现选自己的节点个数超过 majority 的个数的时候,自己就是领头节点
(4)如果没有一个sentinel达到了majority的数量,等一段时间,重新选举
4、故障转移:
有了领头sentinel之后,下面就是要做故障转移了,故障转移的一个主要问题和选择领头sentinel问题差不多,到底要选择哪一个slaver节点来作为master呢?按照我们一般的常识,我们会认为哪个slave节点中的数据和master中的数据相识度高哪个slaver就是master了,其实哨兵模式也差不多是这样判断的,不过还有别的判断条件,详细介绍如下:
(1)在进行选择之前需要先剔除掉一些不满足条件的slaver,这些slaver不会作为变成master的备选
- 剔除列表中已经下线的从服务
- 剔除有5s没有回复sentinel的info命令的slave
- 剔除与已经下线的主服务连接断开时间超过 down-after-milliseconds * 10 + master宕机时长 的slaver
(2)选主过程:
- 选择优先级最高的节点,通过sentinel配置文件中的replica-priority配置项,这个参数越小,表示优先级越高
- 如果第一步中的优先级相同,选择offset最大的,offset表示主节点向从节点同步数据的偏移量,越大表示同步的数据越多
- 如果第二步offset也相同,选择run id较小的
5、修改配置:
新的master节点选择出来之后,还需要做一些事情配置的修改,如下:
- 领头sentinel会对选出来的从节点执行slaveof no one 命令让其成为主节点
- 领头sentinel 向别的slave发送slaveof命令,告诉他们新的master是谁谁谁,你们向这个master复制数据
- 如果之前的master重新上线时,领头sentinel同样会给起发送slaveof命令,将其变成从节点