一.概述

  Sentinel(哨岗或哨兵)是Redis的高可用解决方案:由一个或多个Sentinel实例(instance)组成的Sentinel系统(system)可以监视任意多个主服务器,以及这些主服务器属下的所有从服务器,并在被监视的主服务器进入下线状态时,自动将下线主服务器属下的某个从服务器升级为新的主服务器,然后由新的主服务器代替已下线的主服务器继续处理命令请求。

  1.1 下面是一个Sentinel系统与主从服务器之间的关系:

    (1) 双环图案的server1是当前的主服务器,以及server2、server3、server4三个从服务器。

    (2) 三个从服务器复制主服务器的写入命令数据,实现数据同步。

    (3) Sentinel系统则监视所有四个服务器。

  1.2  Sentinel系统监视主服务器下线

    当主服务器server1进入下线状态,那么三个从服务器复制操作被中止,由Sentinel系统监视到了server1已下线,当server1的下线时长超过用户设定的下线时长时,Sentinel系统就会对server1执行自动故障迁移。下面是Sentinel系统监视到了server1主服务器已下线:

    只有具备故障转移功能,才是一个高可用的解决方案。Sentinel系统自动执行故障转移步骤:

    (1) 首先Sentinel系统会挑选一个从服务器,并将这个选中的从服务器升级为新的主服务器。 

    (2) 之后 Sentinel系统会让所有从服务器都开始复制新的主服务器,故障转移操作执行完毕。

    (3) Sentinel系统还会继续监视已下线的server1,并在它重新上线时,将它设置为从服务器。

二. Sentinel服务器初始化过程介绍

   2.1 初始化一个普通的Redis服务器

    因为Sentinel服务器本质上只是一个运行在特殊模式下的Redis服务器,所以启动Sentinel的第一步,就是初始化一个普通的Redis服务器。初始化服务器在介绍“服务器章节”中讲到过。由于工作不同,Sentinel的初始化过程和普通Redis服务器的初始化过程并不完全相同。比如:Sentinel就不会载入RDB文件或者AOF文件。下面表格展示Sentinel模式下运行时,服务器各个主要功能使用情况:

功能 使用情况
数据库和键值对方面的命令,如set,del,flushdb 不使用
事务命令,如multi和watch 不使用
脚本命令,如eval 不使用
RDB持久化命令,如save和bgsave 不使用
AOF 持久化命令,如bgrewriteaof 不使用

复制命令,如slaveof

Sentinel内部可以使用,但客户端不可以使用
发布与订阅命令,如publish和subscribe Subscribe,psubscribe,unsubscribe,punsubscribe四个命令在Sentinel内部和客户端都可以使用,但publish命令只能在Sentinel内部使用
文件事件处理器,(负责发送命令请求,处理命令回复) Sentinel内部使用,但关联的文件事件处理器与普通Redis服务器不同
时间事件处理器,(负责执行serverCron函数) Sentinel内部使用,serverCron函数会调用sentinel.c/sentinelTimer函数,后者包含了Sentinel要执行的所有操作

  

  2.2 服务器内部使用Sentinel专用代码

    启动Sentinel的第二个步骤就是将一部分普通Redis服务器使用的代码替换成Sentinel专用代码。比如:普通Redis服务器端口6379,而Sentinel端口26379,即Sentinel.c/redis_sentinel_port常量。还有命令表也不一样,对于Sentinel的客户端就只有ping, sentinel,info, Subscribe,psubscribe,unsubscribe,punsubscribe 这7个命令,即Sentinel.c/sentinelcmds作为服务器的命令表。

  

  2.3 初始化Sentinel状态

    应用了专用代码之后,步骤三是服务器会初始化一个Sentinel.c/sentinelstate结构,这个结构保存了服务器中所有和Sentinel功能有关的状态,对于服务器一般状态还是由redis.h/redisServer结构保存。

  2.4 初始化Sentinel状态的masters属性

    sentinel状态中的masters字典记录了所有被sentinel监视的主服务器的相关信息,其中字典的键是被监视的主服务器名字,而字典的值是被监视主服务器对应的sentinel.c/sentinelRedisInstance结构。每个sentinelRedisInstance实例结构代表监视一个Redis服务器实例,这个实例可以是主服务器,也可以是从服务器,或者另外一个sentinel服务器。对于sentinel状态的初始化将引发对masters字典的初始化,而masters字典的初始化是根据被该入的sentinel配置文件(sentinel.conf)来进行的。

  2.5 创建连向主服务器的网络连接

    初始化Sentinel的最后一步是创建连向被监听主服务器的网络连接,Sentinel将成为主服务器的客户端,它可以向主服务器发送命令,并从命令回复中获取相关信息。对于被Sentinel监视的主服务器来说,Sentinel会创建两个连向主服务器的异步网络连接

    (1) 一是命令连接,专门用于向主服务器发送命令,并接收命令回复。比如sentinel向主服务器发送:info命令。

    (2) 二是订阅连接,专门用于订阅主服务器的_sentinel_:hello频道。 比如sentinel向主,从,其它sentinel发送sentinel本身和主库信息。

    下面是一个Sentinel监视两个主服务器master1和master2,创建命令连接和订阅连接图:

      命令连接:是sentinel用来对主服务器发送命令,以此来与主服务器进行通信,所以sentinel必须向主服务器创建命令连接。订阅连接:是redis在发布与订阅功能 中,被发送的信息都不会保存在redis服务器中,如果信息发送时,想要接收的客户端不在线或者断线,那么这个客户端就会丢失这条信息,因为为了不丢失_sentinel_:hello频道的任何信息,sentinel必须专门用一个订阅连接来接收该频道的信息。

      

三. 获取服务器信息

  3.1 Sentinel获取主服务器信息

    Sentinel默认会以每10秒一次的频率,通过命令连接向主服务器发送info命令,通过分析info命令的回复来获取主服务器的当前信息,就像在上篇讲到的复制功能,在客户端输入info replication 命令一样,Sentinel可以获取以下两方面的信息:

    (1) 关于主服务器本身的信息,包括服务器run_id,role的服务器角色。

    (2) 关于所有从服务器的信息,每个从服务器都由一个slave字符串开头的行记录,记录了从服务器IP和端口(主服务器中有从库的配置信息)。

  3.2 Sentinel获取从服务器信息

    当Sentinel发现主服务器有新的从服务器出现时,Sentinel除了会为这个新的从服务器创建相应的实例结构(sentinelRedisInstance)之外,Sentinel还会创建连接到从服务器的命令连接和订阅连接。Sentinel默认会以每10秒一次的频率通过命令连接从服务器发送info命令,通过分析info命令的回复来获取从服务器的当前信息。包括:从服务器运行run_ID、从服务器角色role、主服务器的ip及端口、主从服务器的连接状态master_link_status、从服务器的优先级slave_priority。

  3.3  Sentinel向主从服务器发送信息

    在默认情况下, Sentinel会以每2秒一次的频率,通过命令连接向,所有被监视的主服务器和从服务器发送以下格式的命令:

    

    这条命令向服务器的_sentinel_:hello频道发送了一条信息,信息的内容由多个参数组成:

    (1) 以s_开头以参数记录的是sentinel本身的信息。

    (2) 而m_开头的参数记录的则是主服务器的信息,如果sentinel正在监视的是主服务器,那么这些参数就是主服务器的信息,如果sentinel正在监视的是从服务器,那么这些参数记录就是从服务器正在复制的主服务器的信息。

参数 描述
S_ip Sentinel的ip地址
S_port Sentinel的端口号
S_runid Sentinel的运行ID

S_epoch

Sentinel 的当前配置纪元

m_name 主服务器的名字
M_ip 主服务器的IP地址
M_port 主服务器的端口号
M_epoch 主服务器的当前配置纪元

    以下是一条sentinel通过publish命令向主服务器发送的信息示例:

  

    这个示例中sentinel的ip地址为172.0.0.1端口号为26379, 运行ID为后面一串,当前纪元为0。主服务器的名字为mymaster,ip地址为127.0.0.1,端口号为6379, 当前纪元为0。

  3.4  sentinel接收来自主服务器和从服务器的频道信息

    当sentinel与一个主服务器或者从服务器建立起订阅连接之后,Sentinel就会通过订阅连接,向服务器发送以下命令:subscribe_sentinel_:hello 。对于每个与Sentinel连接的服务器,Sentinel既通过命令连向服务器的_sentinel_:hello频道发送信息,又通过订阅连接从服务器的_sentinel_:hello频道接收信息。

    当有三个sentinel,分别是sentinel1、sentinel2 、sentinel3。三个sentinel在监视同一个服务器,那么当sentinel1向服务器的_sentinel_:hello频道发送一条信息时,所有订阅了_sentinel_:hello频道的sentinel(包括sentinel1自己在内)都会收到这条信息。

    当一个sentinel从_sentinel_:hello频道收到一条信息时,sentinel会对这条信息进行分析,提取出信息中sentinel 的 ip 、port、runID等8个参数,并进行以下检查:

    (1) 如果信息中记录的sentinel运行ID和接收信息的sentinel运行ID相同,那么说明这条信息是sentinel自己发送的,sentinel将丢弃这条信息,不做进一步处理。

    (2) 相反地,如果信息中记录的sentinel运行ID和接收信息的sentinel运行ID不相同,那说明这条信息监视同一个服务器的其它sentinel发来的,接收信息的sentinel将根据信息中的参数,对相应主服务器的实例结构进行更新。

  3.5 sentinel更新自己的sentinels字典

    sentinel为主服务器创建实例结构中的sentinels字典,保存了sentinel本身,还监视这个主服务器的其他sentinel的资料。当一个sentinel接收到其他sentinels发来的信息时,接收的sentinel会从信息中分析并提取出两方面参数:

    (1)与sentinel有关的参数,包括sentinel的ip、port、runid、配置纪元。

    (2)与主服务器有关的参数, 包括监视主服务器的ip、port、runid、配置纪元。

    假设分别有三个sentinel: 127.0.0.1:26379、127.0.0.1:26380、127.0.0.1:26381。三个sentinel正在监视主服务器127.0.0.1:6379, 那么当127.0.0.1:26379这个sentinel接收到以下消息时:

    这个sentinel将执行以下动作:

    (1) 第一条信息发送者为自己,信息忽略。

    (2) 第二条信息发送者为26381, sentinel会根据信息提取出内容,对sentinels字典中26381对应的实例结构进行更新。

    (3) 第三条信息发送者为23680,同样更新字典中的23680对应的实例结构。

    每个sentinel都有自己的一个sentinels字典, 对于26379的sentinel它的sentinels字典信息保存了26380和26381两个sentinel信息。其它sentinel也一样。

  3.6 sentinel创建连向其他sentinel的命令连接

    当sentinel通过频道信息发现一个新的sentinel时,不仅更新sentinels字典,还会创建一个连向sentinel命令连接,而新的sentinel也会创建连向这个sentinel的命令连接,最终监视同一个主服务器的多个sentinel将形成相互连接的网络。如下图所示:

redis 系列23 哨兵Sentinel (上)的更多相关文章

  1. redis 系列25 哨兵Sentinel (高可用演示 下)

    一. Sentinel 高可用环境准备 1.1 Sentinel 集群环境 环境 说明 操作系统版本 CentOS  7.4.1708  IP地址 172.168.18.200 网关Gateway 1 ...

  2. redis 系列24 哨兵Sentinel (中)

    四. 检测下线状态 对于Redis的Sentinel中关于下线有两个不同的概念:(1)主观下线(Subjectively Down, 简称 Sdown) 指的是单个 Sentinel 实例对服务器做出 ...

  3. Redis 主从、哨兵Sentinel、Jedis

    Redis 主从.哨兵Sentinel.Jedis 2017年02月15日 15:52:48 有且仅有 阅读数 6183 文章标签: redis主从sentineljedis 更多 分类专栏: 7/1 ...

  4. redis系列--深入哨兵集群

    一.前言 在之前的系列文章中介绍了redis的入门.持久化以及复制功能,如果不了解请移步至redis系列进行阅读,当然我也是抱着学习的知识分享,如果有什么问题欢迎指正,也欢迎大家转载.而本次将介绍哨兵 ...

  5. redis系列:哨兵

    1 简介 Sentinel(哨兵)是Redis 的高可用性解决方案:通过哨兵可以创建一个当主服务器出现故障时自动将从服务器升级为主服务器的一个分布式系统.解决了主从复制出现故障时需要人为干预的问题. ...

  6. Redis系列五 - 哨兵、持久化、主从

    问:骚年,都说Redis很快,那你知道这是为什么吗? 答:英俊潇洒的面试官,您好.我们可以先看一下 关系型数据库 和 Redis 本质上的区别. Redis采用的是基于内存的,采用的是单进程单线程模型 ...

  7. redis 系列21 复制Replication (上)

    一.   概述 使用和配置主从复制非常简单,每次当 slave 和 master 之间的连接断开时, slave 会自动重连到 master 上,并且无论这期间 master 发生了什么, slave ...

  8. 【目录】redis 系列篇

    随笔分类 - redis 系列篇 redis 系列27 Cluster高可用 (2) 摘要: 一. ASK错误 集群上篇最后讲到,对于重新分片由redis-trib负责执行,关于该工具以后再介绍.在进 ...

  9. Redis系列4:高可用之Sentinel(哨兵模式)

    Redis系列1:深刻理解高性能Redis的本质 Redis系列2:数据持久化提高可用性 Redis系列3:高可用之主从架构 1 背景 从第三篇 Redis系列3:高可用之主从架构 ,我们知道,为Re ...

随机推荐

  1. python基础day2

    一.python字符串 字符串是 Python 中最常用的数据类型.可以使用引号('或")来创建字符串 1.1Python访问字符串中的值 Python不支持单字符类型,单字符在 Pytho ...

  2. git 的常用命令(未完待补充)

    一.初始化 git git init 这样会默认创建 master 分支 二.查看当前状态 git status  查看 git 的默认状态 三.创建一个文件,并把它添加到 git 仓库,使用 git ...

  3. 转载 CSDN 谈谈我对证券公司一些部门的理解(前、中、后台)

    谈谈我对证券公司一些部门的理解(前.中.后台) 2018年02月08日 15:11:07 unirong 阅读数:2165   文中对各大部门的分析都是从作者多年经历总结出来的有感之谈,尤其是前台的6 ...

  4. NEERC训练实录

    听说这里可以做一些idea比较好的题.. 那就做做吧 2017-2018 ACM-ICPC, NEERC, Northern Subregional Contest A. Auxiliary Proj ...

  5. vue Error: No PostCSS Config found in

    最近在做一个vue的移动端的项目,遇到一个问题,我本地的项目运行正常,可是上传到github上的一启动就报错,就是标题上的错误,找了很久,刚开始以为是某个css没有配置,就把本地的复制过去还是报错,无 ...

  6. Git Log描述乱码问题解决方法

    在git bash 中执行以下命令:git config --global core.quotepath off git config --global --unset i18n.logoutpute ...

  7. msxfs.dll函数加载代码

    msxfs.dll函数加载代码 #include "stdafx.h" #include "WSXFSLoader.h" NS_AWP_DEVICE_WOSA_ ...

  8. 从C过渡到C++的几个知识点(结构体、引用、重载运算符)

    一.结构体和类(class) 下面一个使用结构体类型的例子 #include <iostream> using namespace std; struct Point{ // 声明Poin ...

  9. nvidia-smi GPU异常消失 程序中断

    GPU型号为NVIDIA的1080Ti,最近出现的状况的是某一个GPU突然就出问题了,如果在该GPU上有运行程序的话则程序中断,nvidia-smi显示出来的GPU则少了这一个. 1.一开始怀疑是温度 ...

  10. 使用ANY和ALL条件

    在比较运算符中,可以出现ALL和ANY,表示“全部”和“任一”,但是ALL和ANY不能单独使用,需要配合单行比较操作符>.>=.<.<=一起使用.其中: > ANY : ...