《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

原文发布于微信公众号 - 决胜机器学习(phpthinker)

原文发表时间:2017-09-13

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏Golang语言社区

【Go 语言社区】[Golang]优秀开源库剖析

原创文章,转载请注明出处:服务器非业余研究http://blog.csdn.net/erlib 作者Sunface 1.blelve 地址:h...

3548
来自专栏容器化

转载NodePort,LoadBalancer还是Ingress?我该如何选择 - kubernetes

2154
来自专栏Golang语言社区

厚土Go学习笔记 | 36. web服务指定路径下的get参数接收与处理

当我们使用go建立了服务器,那么一种常见的需求就摆在面前。如何给这个服务器的某个路径传参数呢?我们研究一下URL传参的接收与处理。 对于 http.Reques...

3308
来自专栏恰同学骚年

NoSQL初探之人人都爱Redis:(1)Redis简介与简单安装

  随着互联网Web2.0网站的兴起,传统的关系数据库在应付Web2.0网站,特别是超大规模和高并发的SNS类型的Web2.0纯动态网站已经显得力不从心,暴露了...

672
来自专栏aCloudDeveloper

UNIX环境高级编程笔记之文件I/O

一、总结   在写之前,先唠几句,《UNIX环境高级编程》,简称APUE,这本书简直是本神书,像我这种小白,基本上每看完一章都是“哇”这种很吃惊的表情。其实大概...

18610
来自专栏微服务

微服务实践分享与探讨

服务调用关系 ? API网关优缺点 简化沟通方式 API网关对所有微服务提供单一的访问点 安全性 对客户端隐藏了服务发现和服务版本 阻止大规模攻击,包括S...

3157
来自专栏张戈的专栏

解决Tomcat数据连接池无法释放

近段时间,公司的检测中心报表系统(SMC)的开发人员时不时找到我,说用户老是出现无法登录的情况。前些日子因为手头上有 Jboss 集群的测试工作,发现用户不能登...

2939
来自专栏YouMeek

1.1 Elasticsearch 介绍 + CentOS 7 下安装部署

课程环境 CentOS 7.3 x64 JDK 版本:1.8(最低要求),主推:JDK 1.8.0_121 Elasticsearch 版本:5.2.0 相关软...

2759
来自专栏猿天地

spring boot开发的日志系统

项目采用技术:springboot,mongodb,freemarker,bootstrap,highcharts等 这个项目还没做完,目前已完成的功能有下面几...

3169
来自专栏linux驱动个人学习

了解adb的基本原理

ADB就是Android调试桥的意思,很形象。但不知道是windows本身的原因还是windows乱七八糟软件太多,用USB调试手机时,经常连不上ADB,或者就...

3689

扫描关注云+社区