上一篇 我们模拟了单机器下哨兵模式的搭建,那么接下来我们看下哨兵模式的实现与工作。

为什么又分成两篇呢?因为篇幅太长(偷懒),再一个这篇主要说的是Sentinel的初始化以及信息交换,下一篇着重说下状态检查、Sentinel头领选举与故障转移 。

启动并初始化Sentinel

当一个Sentinel启动时,需要执行以下步骤:

(1)初始化服务器。

因为Sentinel本事上是一个运行在特殊模式下的Redis服务器,所以启动时的第一步也就是初始化一个普通的Redis服务器。不同点是在初始化的时候不会载入RDB或AOF文件。

(2)将普通的Redis服务器使用的代码替换成Sentinel专用代码。

端口替换Redis服务器使用redis.h/REDIS_SERVERPORT(6379)常量作为服务器端口,而Sentinel则使用sentinel.c/REDIS_SENTINEL_PORT(26379)常量作为服务器端口。

另外Redis服务器使用redisCommandTable服务器作为命令表,而Sentinel则使用sentinelcmds作为服务器的命令表,并且其中的info命令会使用Sentinel模式下专用的sentinelInfoCommand函数,而不是普通redis服务器使用的redis.c/infoCommand函数。

(3)初始化Sentinel状态。

服务器会初始化一个sentinel.c/sentinelState结构('Sentinel状态'),用于保存服务器中所有和Sentinel功能有关的状态。

struct sentinelState{
//当前纪元,用于实现故障转移
uint64_t current_epoch;
//保存了所有被这个sentinel监视的主服务器
//字典的键是主服务器的名字
//字典中的值是一个指向sentinelRedisInstance结构的指针
dict *masters;
//是否进入TILT模式
int tilt;
//目前正在执行的脚本数量
int running_scripts;
//进图TILT模式的时间
mstime_t tilt_start_time;
//一个FIFO队列,包含了所有需要执行的用户脚本
list *scripts_queue;
} sentinel;

(4)根据给定的配置文件,初始化Sentinel的监视主服务器列表。

sentinelRedisInstance结构(实例结构)

typedef struct sentinelRedisInstance{
//标识值,记录了实例的类型以及该实例的当前状态
int flag;
//实例的名称(主服务器由用户配置,从服务器自动设置ip:port)
char *name;
//实例的运行id
char *runid;
//配置纪元,用户实现故障转移
uint64_t config_epoch;
//实例的地址
//sentinelAddr *addr;
//实例无相应多少毫秒之后才会被判断主观下线
mstime_t down_after_period‘;
//判断这个实例为客观下线所需要支持的投票数量
int quorun;
//在执行故障转移操作时,可以同时对新的主服务器进行同步的从服务器数量
int parallel_syncs;
//刷新故障迁移状态的最大时间限制
mstime_t fallover_timeout;
} sentinelRedisInstance;

*addr 指向sentinelAddr结构:

typedef struct sentinelAddr{
char *ip;
int port;
} sentinelAddr;

根据用户的配置初始化实例结构:

#名称 ip port

sentinel monitor mymaster 127.0.0.1 6379 2

#实例在相应多少毫秒之后才会被判断主观下线

sentinel down-after-milliseconds mymaster 3000

sentinel failover-timeout mymaster 10000

#在执行故障转移操作时,可以同时对新的主服务器进行同步的从服务器数量

sentinel parallel-syncs mymaster 1

(5)创建连向主服务器的网络连接。

Sentinel将称为主服务器的客户端,它可以向主服务器发送命令,并从命令回复中获取相关的信息:对于被Sentinel监视的主服务器来说,Sentinel会创建两个连向主服务器的异步网络连接,一个是命令连接这个连接专门用于向主服务器发送命令,并接收命令回复;另一个是订阅连接这个连接专门用于订阅主服务器的_sentinel_:hollo频道。

 获取主服务器信息

sentinel默认会以每十秒一次的频率,通过命令连接向被监视的主服务器发送INFO命令,并通过分析INFO命令的回复来获取主服务器的当前信息。

通过分析主服务器返回的INFO命令回复,Sentinel可以获取以下两个方面的信息:

一方面是关于主服务器本身的信息,包括run_id域记录的服务器运行ID以及role域记录的服务器角色;另一方面是关于主服务器属下的所有从服务器信息,每个从服务器由一个“slave”字符串开头的行记录,每行的ip=域记录了从服务器的IP地址,而port=域则记录了从服务器的端口号。根据这些IP地址和端口号,Sentinel无须用户提供从服务器的地址信息,就可以自动发现从服务器。

主服务器 实力结构的flags属性的值为SRI_MASTER,而从服务器实例结构的flags属性的值为SRI_SLAVE。

当Sentinel发现主服务器有新的从服务器出现时,Sentinel除了会为这个新的从服务器创建相应的实例结构外,Sentinel还会创建连接到从服务器的命令连接和订阅连接。

在默认情况下,Sentinel会以每两秒一次的频率,通过命令连接向所有被监视的主服务器和从服务器发送以下格式的命令,PUBLISH _sentinel_:hello "< s_ip > < s_port >< s_runid >< s_epoch > < m_name > < m_ip >< m_ip ><m_epoch>"。

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

当Sentinel与一个主服务器或者从服务器建立起订阅连接之后,Sentinel就会通过订阅连接,向服务器发送以下命令:SUBSCRIBE __semtomel__:hello

当一个Sentinel从__sentinel__:hello频道收到一条信息时,Sentinel会对这条信息进行分析,提取出信息中的Sentinel IP地址,Sentinel端口号,Sentinel运行ID等八个参数,并进行检查:如果信息中记录的Sentinel运行ID和基尔兽信息的Sentinel的运行ID相同,那么说明这条信息时Sentinel自己发送的,Sentinel将丢弃这条信息,不做处理,反之如果记录的Sentinel运行ID和接收消息的Sentinel的运行ID不相同,那么说明这条信息时监视同一个服务器的其他Sentinel发来的,接收信息的Sentinel将根据这些信息中的参数,对相应主服务器的实例结构进行更新。

Sentinel为主服务器创建的实例结构中的sentinels字典中除了保存本身以外,还会保存同样监视这个主服务器的其他Sentinel的资料,其中字典键为 ip:port 值为Sentinel实例结构。

如果目标Sentinel(接收消息的Sentinel)接收到源Sentinel(发送消息的Sentinel)的消息,提取其中的参数检查主服务器实例结构的sentinels字典中源Sentinel实例结构是否存在,如果存在则更新,不存在则创建实例结构并存储到主服务器的sentinels字典中。并且,目标Sentinel还会创建连接向源Sentinel的命令连接,最终监视同一主服务器的多个Sentinel将形成互相连接的网络。

但是Sentinel之间不对创建订阅连接,这是因为Sentinel需要通过接收主服务器或者从服务器发来的频道信息发现未知的新Sentinel,所以才需要建立订阅连接,而相互已知的Sentinel只要使用命令连接来进行通信就足够了。


每天学一点,总会有收获。

下篇我们看下Redis的Sentinel(哨兵)的状态检查、Sentinel头领选举与故障转移。

说明:尊重作者知识产权,文中内容参考《Redis设计与实现》,仅在此做学习与大家分享。


Redis学习笔记(十五)Sentinel(哨兵)(中)的更多相关文章

  1. python3.4学习笔记(十五) 字符串操作(string替换、删除、截取、复制、连接、比较、查找、包含、大小写转换、分割等)

    python3.4学习笔记(十五) 字符串操作(string替换.删除.截取.复制.连接.比较.查找.包含.大小写转换.分割等) python print 不换行(在后面加上,end=''),prin ...

  2. (转载)西门子PLC学习笔记十五-(数据块及数据访问方式)

    一.数据块 数据块是在S7 CPU的存储器中定义的,用户可以定义多了数据块,但是CPU对数据块数量及数据总量是有限制的. 数据块与临时数据不同,当逻辑块执行结束或数据块关闭,数据块中的数据是会保留住的 ...

  3. Redis学习笔记(六、哨兵)

    目录: 基本概念 环境部署 哨兵原理 哨兵命令 基本概念: 1.什么是哨兵 我们先从字面意思来了解哨兵,哨兵是对执行警戒任务的士兵的统称:在redis中哨兵也是一样,他监控着redis服务器的状态. ...

  4. (C/C++学习笔记) 十五. 构造数据类型

    十五. 构造数据类型 ● 构造数据类型概念 Structured data types 构造数据类型 结构体(structure), 联合体/共用体 (union), 枚举类型(enumeration ...

  5. Java学习笔记十五:Java中的成员变量和局部变量

    Java中的成员变量和局部变量 一:成员变量: 成员变量在类中定义,用来描述对象将要有什么 成员变量可以被本类的方法使用,也可以被其他类的方法使用,成员变量的作用域在整个类内部都是可见的 二:局部变量 ...

  6. Redis6.x学习笔记(五)哨兵

    前言 最近学习Redis6.x,特做笔记以备忘,与大家共学.课程是从私塾在线下载的,他们把架构师课程都放出来了,大家可以去下载学习,不要钱的,地址是http://t.hk.uy/eK7,课程很不错,值 ...

  7. Redis学习笔记(五) 基本命令:Hash操作

    原文链接:http://doc.redisfans.com/hash/index.html 学习前先明确一下概念,这里我们把Redis的key称作key(键),把数据结构hash中的key称为fiel ...

  8. Redis 学习笔记(五)高可用之主从模式

    上一节提到了 Redis 的持久性,也就是在服务器实例宕机或故障时,拥有再恢复的能力.但是在这个服务器实例宕机恢复期间,是无法接受新的数据请求.对于整体服务而言这是无法容忍的,因此我们可以使用多个服务 ...

  9. MySQL学习笔记十五:优化(2)

    一.数据库性能评测关键指标 1.IOPS:每秒处理的IO请求次数,这跟磁盘硬件相关,DBA不能左右,但推荐使用SSD. 2.QPS:每秒查询次数,可以使用show status或mysqladmin ...

  10. salesforce 零基础开发入门学习(十五)salesforce中formula的使用(不含Date/Time)

    本文参考官方的formula介绍PDF:https://resources.docs.salesforce.com/200/latest/en-us/sfdc/pdf/salesforce_usefu ...

随机推荐

  1. 基于LINUX 主机防火墙的端口转发

    由于centos7之后将默认防火墙从原来的iptables更改为firewall.本文主要记录基于firewall的端口转发部署. 1.检查防火墙状态     systemctl status fir ...

  2. POJ2155/LNSYOJ113 Matrix【二维树状数组+差分】【做题报告】

    这道题是一个二维树状数组,思路十分神奇,其实还是挺水的 题目描述 给定一个N∗NN∗N的矩阵AA,其中矩阵中的元素只有0或者1,其中A[i,j]A[i,j]表示矩阵的第i行和第j列(1≤i,j≤N)( ...

  3. mybatis源码学习(一):Mapper的绑定

    在mybatis中,我们可以像下面这样通过声明对应的接口来绑定XML中的mapper,这样可以让我们尽早的发现XML的错误. 定义XML: <?xml version="1.0&quo ...

  4. SocksCap64应用程序通过SOCKS代理

    一.下载SocksCap64 https://pan.baidu.com/s/1B671kT9R6Zb6ch1mc4Kb2Q 提取码:hai3 一个是免安装版本,一个是安装版本,选一个即可. 下面以免 ...

  5. 图论--网络流--费用流--POJ 2156 Minimum Cost

    Description Dearboy, a goods victualer, now comes to a big problem, and he needs your help. In his s ...

  6. HDU-1857 畅通工程再续

    畅通工程再续 Problem Description 相信大家都听说一个"百岛湖"的地方吧,百岛湖的居民生活在不同的小岛中,当他们想去其他的小岛时都要通过划小船来实现.现在政府决定 ...

  7. RF(控制台及日志输出中文乱码)

    1.查看 ride 版本,我这里是 RIDE 1.7.4.1 running on Python 3.6.0. 2.修改文件 D:\python3.6\Lib\site-packages\roboti ...

  8. .net core 基于Dapper 的分库分表开源框架(core-data)

    一.前言 感觉很久没写文章了,最近也比较忙,写的相对比较少,抽空分享基于Dapper 的分库分表开源框架core-data的强大功能,更好的提高开发过程中的效率: 在数据库的数据日积月累的积累下,业务 ...

  9. C :uthash

    参考: [1] uthash | 学步园 [2] 源码 [3] 官方文档 [4] [5] 一.哈希表的概念及作用 在一般的线性表或者树中,我们所储存的值写它的存储位置的关系是随机的.因此,在查找过程中 ...

  10. Java模拟UDP通信

    目录 Java基础:模拟UDP通信 1.一次发送,一次接收 1.1.发送方 1.2.接收方 2.多次发送,多次接收 2.1.发送方 2.2.接收方 3.模拟双方通信 3.1.发送方的线程 3.2.接收 ...