《Redis设计与实现》读书笔记(二十七) ——Redis哨兵(sentinel)主服务器下线判断与故障转移

时间:2022-05-03
本文章向大家介绍《Redis设计与实现》读书笔记(二十七) ——Redis哨兵(sentinel)主服务器下线判断与故障转移,主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

《Redis设计与实现》读书笔记(二十七) ——Redis哨兵(sentinel)主服务器下线判断与故障转移

(原创内容,转载请注明来源,谢谢)

一、主观下线检测

默认情况下,sentinel会每秒1次,向所有它创建的连接实例发送ping命令,包括主从服务器与其他的sentinel。通过实例返回判断是否在线。

有效的回复包括pong、loading和mastdown,无效的回复包括超时的回复以及前三个之外的回复。

在sentinel的配置文件中,down_after_milliseconds指定了sentinel判断主观下线的方式,主服务器连续没给出正确的回复超过这个设定的时间,则表示该主服务器被这个sentinel认定为主观下线。

此时,sentinel会在自身记录主服务器的flags加上一个标签,使得主服务器此时的flags标签变为SRI_MASTER|SRI_S_DOWN。

配置主观下线的down_after_milliseconds,不仅sentinel会对该主服务器进行这样的判断,也同样会将该参数带到该主服务器下的全部从服务器。

另外,不同的sentinel对同一个主服务器,设定的主观下线的值可以不同。每个sentinel会按照自身的配置文件,来判断检测的主服务器是否主观下线。

二、客观下线检测

1、发送检测主观下线命令

当sentinel认定该主服务器主观下线,会同时给其他几个监测此主服务器的sentinel发送命令,确认在其他sentinel处是否也认为该主服务器主观下线。命令格式为:

         sentinel is-master-down-by-addr <ip><port> <current_epoch> <runid>

其中,runid如果是*,表示仅仅检测该主服务器是否主观下线,如果是用sentinel的运行id,则表示选举领头sentinel。

2、接收命令回复

sentinel会收到包含三个参数的multi bulk回复,如下:

1)<down_state>

目标sentinel对该主服务器的检查结果,1表示该sentinel也认为主服务器主观下线,0表示未下线。

2)<leader_runid>

*或者sentinelid,*表示主服务器,sentinelid表示局部主服务器id。

3)<leader_epoch>

领头纪元,用于选举主服务器。

3、客观下线

当回复的sentinel中,认为该主服务器主观下线的个数超过配置文件中设定的quorum的值(包括自身是sentinel),则sentinel认为该主服务器客观下线。

sentinel会给该主服务器加上一个新的flags标签,总体标签变为:SRI_MASTER|SRI_S_DOWN|SRI_O_DOWN。

不同的sentinel可以设置不同的客观下线quorum数量,因此可能部分sentinel认为主服务器客观下线,另一部分认为还没客观下线。

三、选举领头sentinel

当一个主服务器被判定为客观下线,监视该主服务器的各个sentinel,会协商选举一个领头sentinel,对下线主服务器进行故障转移工作。

方式如下:

1)所有在线的sentinel都有参选资格。

2)每次选举领头sentinel,无论是否成功,所有sentinel的配置纪元(epoch)都会加一,这个epoch即计数器。

3)在每一轮的epoch,每个sentinel都有一次机会将某个sentinel设置为局部领头sentinel,设置后在本轮的epoch不可更改。

4)每个发现主服务器客观下线的sentinel都会要求其他的sentinel将自身设置为局部领头。

5)当一个sentinel向另一个sentinel发送sentinelis-master-down-by-addr <ip> <port> <current_epoch> <runid>,其中的runid不是*,而是源sentinel的运行id,则表示源sentinel要求接收者将自身选举为局部领头。

6)设置局部领头的规则是先到先得,先发送的会被设置为领头,后面发送的会被拒绝。

7)目标sentinel接收到第五步的命令后,回复的结果中,<leader_runid>就是源sentinel的运行id,<leader_epoch>是本轮的epoch。

8)源sentinel接收到回复后,会比对runid,如果和自身的一致,则表示目标sentinel已经将源sentinel设置为局部领头。

9)如果某个sentinel被设置为局部领头的数量,超过总sentinel的一半(不含正好一半的情况),则其称为领头sentinel。

10)因为需要半数以上支持,因此每次epoch只会有一个sentinel被选为领头。

11)一定时间内,如果没有选举出领头,则会在一段时间后,再次进行选举。

四、故障转移

选举领头后,领头sentinel将进行故障转移,工作包括:

1)在下线的主服务器对应的从服务器里面,重新选一个主服务器;

2)让其余的从服务器都称为新主服务器的从服务器;

3)把下线的旧主服务器也设置为新主服务器的从服务器,这样其上线后就以从服务器的方式运作。

1、选出新主服务器

sentinel会将下线的主服务器的从服务器列表中,选出一个从服务器,选择规则如下:

1)不考虑已经下线和断线的从服务器,以保证选出的是正常在线的。

2)不考虑最近5秒内没有回复过领头sentinel的info命令的从服务器,以保证选出的是成功通信的。

3)不考虑所有和已下线主服务器断开连接超过down-after-millisecond*10毫秒的从服务器,以保证选出的是数据最新的。

4)将剩余的从服务器,按照从服务器优先级选择主服务器。

5)如果优先级一样,则按照偏移量最大的选择。

6)如果优先级和偏移量都一样的,按照运行ID最小的作为主服务器。

选出主服务器后,sentinel给其发送slaveofno one命令,让其变成主服务器。并且,会每秒一次的频率发送info命令给新主服务器(正常是10秒一次发送info),直到回复中role从slave变成master,表示升级成功。

2、修改其他从服务器的复制目标

即给其余的从服务器,发送slaveof<new_ip> <new_port>,让其余的从服务器重新选则新的主服务器。

3、将旧主服务器变成从服务器

由于其已经下线,无法直接发送slaveof命令,sentinel会将其保存在实例结构里面,待其重新上线,再发送命令。

五、重点回顾

1、sentinel服务器是运行在特殊模式下的redis服务器,其命令表、默认端口都和redis服务器有所不同,只接受7个客户端的命令,默认端口是26379。

2、sentinel会读入用户的主从配置文件,与每个要监视的主服务器创建实例结构,并且创建命令连接和订阅连接,命令连接用来发送ping、publish、info等命令,订阅连接用来监听该主服务器下的所有从服务器的状态。sentinel同样会和从服务器建立这样的两个连接,但是和其他的sentinel只会建立命令连接,没有订阅连接。

3、sentinel通过向监听的主服务器发送info命令,获取并建立相关从服务器的实例结构。info命令通常10秒1次,但是在重新选出的主服务器还未完全从从服务器转成主服务器时,是每秒发送一次info。

4、对于所有监视主从服务器的sentinel,服务器会两秒发送一个__sentinel__:hello频道内容,表示自己还在线。

5、每个sentinel也会从上述频道接收到其他sentinel的信息,并且更新到自身的相应的实例结构中。

6、sentinel每秒1次向所有实例结构(主、从服务器以及其他sentinel服务器)发送ping命令,根据回复判断是否在线,超过规定时间仍是无效回复,则认为该服务器主观下线。

7、当sentinel认为主服务器主观下线,会给其他sentinel发送命令,查询是否其他sentinel也认为其主观下线。当收到的回复中,认为主服务器主观下线的sentinel个数(含自身)超过设置的值,则sentinel认为该主服务器客观下线。

8、判断主服务器客观下线后,sentinel会选出一个领头sentinel,来进行故障转移的工作,选举主要是要拿到超过半数的临时领头。

9、故障转移工作,包括从从服务器中新选出一个主服务器、将其他从服务器复制的对象改为新主服务器、将下线的旧主服务器改为从服务器。

——written by linhxx 2017.09.13