redis: sentinel

2021-09-20  本文已影响0人  布拉德老瓜

1.概述

redis主从复制解决了单机下数据丢失的问题,在一主多从的结构下,倘若master出现故障,slaves仍然有数据备份。此时一个自然而然的想法就涌现出来了:在master不可用的情况下,能否重新调整主从关系,从slave中选取一个服务器作为新的master,从而实现redis的高可用。sentinel就是这样一种解决方案:由一组哨兵(sentinel)实例组成一个sentinel系统,该系统保证其自身高可用性的同时,监控redis主服务器和该主服务器所属的从服务器,当主服务器下线时长超过阈值之后,由sentinel系统挑选一个从服务器,将该服务器升级为新的主服务器,完成故障转移。同时,sentinel还持续监控已下线的服务器,当他重新上线时,将该服务器设为新的master下的slave。

sentinel系统的运行流程如图:

  1. 假设现有一个master和3各slave。通过配置sentinel系统,使其监控这些服务器


    sentinel系统监控master和其所属的slave
  2. 当master服务器(server1)下线, 主从复制将会被终止。同时,sentinel感知到server1下线。


    主服务器下线

    3.master下线时间超过阈值,sentinel系统开始故障转移。在slave中选取一个服务器(如server2),作为新的master,让其他的服务器作为server2的从服务器。另一边,sentinel持续监控server1的状态。


    选举新的主服务器,持续监控下线服务器
  3. 当server1重新上线时,sentinel通过SLAVEOF命令将其设置为server2的从服务器。


    下线主机重新上线,降级为从服务器

2.sentinel启动运行全流程

2.1启动sentinel

创建一个类型为sentinel的redis服务器。它本质上仍然是一个redis服务器,但其工作方式和普通redis服务器不同,主要体现在它需要维护各master和master下slave的在线信息。


image.png

1.1. 替换服务器代码为Sentinel专用代码Redis_Server_Port --> Redis_Sentinel_Port; redisCommandTable --> sentinelcmds。
1.2. 由服务器初始化Sentinel状态,创建一个sentinelState结构,主要维护了一个保存masters信息的字典。
1.5. 服务器读取sentinel.conf文件,完成Sentinel中masters属性的配置。假设在配置文件中配置了master1和master2,那么masters的状态如图。


image.png
1.4. 创建与各master的连接,准备与master通信

2.2. 获取主服务器信息

2.1. 主服务器本身的信息: run_id: xxx, role:master 
2.2 slave信息 ip, port, state, offset ...
image.png

获取到服务器信息之后,即可更新服务器实例信息,如下图:


image.png

2.3. 获取从服务器信息

当有新的从服务器通过SLAVEOF成为主服务器的slave时,master的回复信息终将会包含该服务器的信息。Sentinel一方面要为该服务器创建实例结构, 另一方面还需要创建到该服务器的命令连接和订阅连接。连接创建后,sentinel每10秒向从服务器发送INFO命令,获取从服务器的信息,包括run_id, role, masterhost: master_port, 复制偏移量...

2.4. 以一定频率向主、从服务器发送信息

每2秒向所有被监视的主、从服务器发送 PUBLISH sentinel: hello "<...>"命令。

2.5. 接收主、从服务器的信息

通过订阅连接,向服务器发送 SUBSCRIBE sentinel:hello命令。一台sentinel像某台master/slave发送的信息也会被其他订阅了该服务器的sentinel收到。该功能的作用在于:使各个sentinel之间能通过主/从服务器相互通信。 根据收到的消息,如果是自己发送的,那么就丢弃;如果是其他sentinel发送的,就根据信息中的各个参数更新主服务器的实例结构,更新sentinels字典,此时各个sentinel中就可以保存彼此的ip:port,接下来创建链接并相互通信就顺理成章了。

image.png
image.png
image.png

2.6. 检测下线状态

2.6.1 主观下线状态

sentinel默认每秒向所有与他创建了连接的实例(master, slave, sentinel)发送PING命令,通过回复状态来判断实例是否在线。每个sentinel对服务器实例的下线判断都是依靠它自身与服务器之间的连接,有可能二者之间通信不顺畅,导致该sentinel判断对方下线,但并不意味着对方真的下线了,因此这种情况称之为主观下线;实例是否真的下线了,要依靠所有sentinel投票。


image.png

回复内容只有3种有效: -PONG, -LOADING, -MASTERDOWN
如果一个实例在一定时间内,连续向sentinel返回无效回复,则sentinel修改该实例对应的状态,将其标记为主观下线。

2.6.2 客观下线状态

当一个sentinel将主服务器标记为主观下线状态之后,会向其他监视该服务器的sentinel发送请求,看他们是否也认为该服务器处于下线状态。当认为下线的sentinel超过配置的阈值时,表明客观下线,将主服务器实例标记为客观下线状态

2.7. 选举sentinel leader

当sentinel将一个主服务器被判定为客观下线之后,会发送请求给监视它的各sentinel,选举出一个leader sentinel,然后由leader sentinel来进行故障转移。

Sentinel集群正常运行的时候每个节点epoch相同,当需要故障转移的时候会在集群中选出Leader执行故障转移操作。Sentinel采用了Raft协议实现了Sentinel间选举Leader的算法,不过也不完全跟论文描述的步骤一致。Sentinel集群运行过程中故障转移完成,所有Sentinel又会恢复平等。Leader仅仅是故障转移操作出现的角色。

选举流程

2.8. 故障转移

8.1. 由leader sentinel重新选取新的master
8.2 修改从服务器的复制目标
8.3 监控旧的master,上线后将其设置为新的master下的slave

上一篇下一篇

猜你喜欢

热点阅读