Sentinel(哨岗、哨兵)是Redis的高可用性(high availability)解决方案:由一个或多个Sentinel实例组成的Sentinel系统可以监视任意多个主服务器,以及这些主服务器属下的所有从服务器,并在被监视的主服务器进入下线状态时,自动将下线主服务器属下的某个从服务器升级为新的主服务器,然后由新的主服务器代替已下线的主服务器继续处理命令请求。
启动并初始化Sentinel
1.初始化服务器
Sentinel本质上只是一个运行在特殊模式下的Redis服务器,所以启动Sentinel的第一步,就是初始化一个普通的Redis服务器,不过,因为Sentinel执行的工作和普通Redis服务器执行的工作不同,所以Sentinel的初始化过程和普通Redis服务器的初始化过程并不完全相同。
2.使用Sentinel专用代码
3.初始化Sentinel状态。
4.根据给定的配置文件,初始化Sentinel的监视主服务器列表。
5.创建连向主服务器的网络连接(一个命令连接,一个订阅连接)。
获取主服务器信息
Sentinel默认会以每十秒一次的频率,通过命令连接向被监视的主服务器发送INFO命令,并通过分析INFO命令的回复来获取主服务器的当前信息。
获取从服务器信息
当Sentinel发现主服务器有新的从服务器出现时,Sentinel除了会为这个新的从服务器创建相应的实例结构之外,Sentinel还会创建连接到从服务器的命令连接和订阅连接。
在创建命令连接之后,Sentinel在默认情况下,会以每十秒一次的频率通过命令连接向从服务器发送INFO命令,并通过分析INFO命令的回复来获取从服务器的当前信息。
向主服务器和从服务器发送信息
在默认情况下,Sentinel会以每两秒一次的频率,通过命令连接向所有被监视的主服务器和从服务器发送以下格式的命令:
PUBLISH __sentinel__:hello "<s_ip>, <s_port>, <s_runid>, <s_epoch>, <m_name>, <m_ip>, <m_port>, <m_epoch>"
这条命令向服务器的__sentinel__:hello频道发送了一条信息,信息参数如下:
接收来自主服务器和从服务器的频道信息
当Sentinel与一个主服务器或者从服务器建立起订阅连接之后,Sentinel就会通过订阅连接,向服务器发送命令:SUBSCRIBE __sentinel__:hello,订阅__sentinel__:hello频道。Sentinel对__sentinel__:hello频道的订阅会一直持续到Sentinel与服务器的连接断开为止。
因此,Sentinel可以通过命令连接向服务器的__sentinel__:hello频道发送信息,又通过订阅连接从
服务器的__sentinel__:hello频道接收信息。
创建与其他Sentinel连接
Sentinel为主服务器创建的实例结构中的sentinels字典保存了除Sentinel本身之外,所有同样监视这个主服务器的其他Sentinel。
当Sentinel通过频道信息发现一个新的Sentinel时,它不仅会为新Sentinel在sentinels字典中创建相应的实例结构,还会创建一个连向新Sentinel的命令连接,而新Sentinel也同样会创建连向这个Sentinel的命令连接,最终监视同一主服务器的多个Sentinel将形成相互连接的网络。
使用命令连接相连的各个Sentinel可以通过向其他Sentinel发送命令请求来进行信息交换。
为什么Sentinel之间不会建立订阅连接?
Sentinel在连接主服务器或者从服务器时,会同时创建命令连接和订阅连接,但是在连接其他Sentinel时,却只会创建命令连接,而不创建订阅连接。这是因为Sentinel需要通过接收主服务器或者从服务器发来的频道信息来发现未知的新Sentinel,所以才需要建立订阅连接,而相互已知的Sentinel只要使用命令连接来进行通信就足够了。
检测主观下线状态
在默认情况下,Sentinel会以每秒一次的频率向所有与它创建了命令连接的实例(包括主服务器、从服务器、其他Sentinel在内)发送PING命令,并通过实例返回的PING命令回复来判断实例是否在线。
如果一个实例在down-after-milliseconds(可在Sentinel配置中配置)毫秒内,连续向Sentinel返回无效回复,那么Sentinel会标记这个实例为主观下线状态。因为多个Sentinel的down-after-milliseconds可能不同,所以可能会出现某个服务器在一个Sentinel里被标记为主观下线状态,在其他Sentinel里仍是正常状态。
检查客观下线状态
当Sentinel将一个主服务器判断为主观下线之后,为了确认这个主服务器是否真的下线了,它会向同样监视这一主服务器的其他Sentinel进行询问,看它们是否也认为主服务器已经进入了下线状态(可以是主观下线或者客观下线)。当认为主服务器已经进入下线状态的Sentinel的数量,超过
Sentinel配置中设置的quorum参数的值时,Sentinel就会将从服务器判定为客观下线,并对主服务器执行故障转移操作。
故障转移
当一个主服务器被判断为客观下线时,监视这个下线主服务器的各个Sentinel会进行协商,选举出一个领头Sentinel,并由领头Sentinel对下线主服务器执行故障转移操作。
在选举产生出领头Sentinel之后,领头Sentinel将对已下线的主服务器执行故障转移操作,该操作包含以下三个步骤:
1.在已下线主服务器属下的所有从服务器里面,挑选出一个从服务器,并将其转换为主服务器。
领头Sentinel会将已下线主服务器的所有从服务器保存到一个列表里面,然后按照以下规则,一项一项地对列表进行过滤:
- 删除列表中所有处于下线或者断线状态的从服务器。
- 删除列表中所有最近五秒内没有回复过领头Sentinel的INFO命令的从服务器。
- 删除所有与已下线主服务器连接断开超过down-aftermilliseconds*10毫秒的从服务器。
- 根据从服务器的优先级,对列表中剩余的从服务器进行排序,并选出其中优先级最高的从服务器。
- 如果有多个具有相同最高优先级的从服务器,那么领头Sentinel将按照从服务器的复制偏移量,对具有相同最高优先级的所有从服务器进行排序,并选出其中偏移量最大的从服务器。
- 如果有多个优先级最高、复制偏移量最大的从服务器,那么领头Sentinel将按照运行ID对这些从服务器进行排序,并选出其中运行ID最小的从服务器。
2.让已下线主服务器属下的所有从服务器改为复制新的主服务器。
当新的主服务器出现之后,领头Sentinel下一步要做的就是,让已下线主服务器属下的所有从服务器去复制新的主服务器,这一动作可以通过向从服务器发送SLAVEOF命令来实现。
3.将已下线主服务器设置为新的主服务器的从服务器,当旧的主服务器重新上线时,它就会成为新的主服务器的从服务器。