redis 高可用 Sentinel 详解

写在前面

redis 在我们日常的业务开发中是十分常见的,而redis的可用性就必须要有很高的要求,那么 redis集群的高可用由有一个或者多个 Sentinel(哨兵) 实例组成的 哨兵系统来保证的。

哨兵

由一个或者多个 Sentinel 实例组成的 Sentinel 系统可以监控任意多个主服务器,以及这些主服务器属下的所有从服务器,并在被监视的主服务器进入下线状态时,自动将下线主服务器属下的某个从服务器升级为新主服务器,然后有新的主服务器代替已下线的主服务器继续处理命令请求。

在这里插入图片描述

简介

Sentinel 本质上只是一个运行在特殊模式下的Redis服务器,但是 Sentinel 和 Redis的初始化和工作内容是不同的。Sentinel 不需要使用数据库,所以初始化的时候是不需要载入RDB文件或者AOF文件的。而Sentinel的工作内容如下:

功能使用情况
数据库键值对命令 SET、DEL、FLUSHDB不使用
事务命令 MULTI,WATCH不使用
脚本命令 EVAL不使用
RDB/AOF持久化命令 SAVE、BGSAVE、BGREWRITEAOF不使用
复制命令,SLAVEOFSentinel 内部使用,但是客户端不用
发布与订阅命令,比如 PUBLISH 和 SUBSCRIBESUBSCRIBE、PSUBSCRIBE、UNSUBSCRIBE、PUBSUBSCRIBE这四个命令在Sentinel内部和客户端都可以使用,但PUBLISH命令只能在Sentinel内部使用
文件事件处理器(负责发送命令和请求、处理命令回复)Sentinel 内部使用,但关联的文件事件处理器和普通Redis处理器不同
事件处理器(负责执行serverCron 函数)Sentinel 内部使用,时间事件的处理器仍然是ServerCron函数,ServerCron函数会调用sentinel.c/sentineTimer函数,后者包含了Sentinel要执行的所有操作

在为什么启动Sentinel的时候,会有这些限制呢?Sentinel 不都是 Redis 吗?

因为在Sentinel初始化的时候,加载的是 src/sentinel.c 文件的函数,而Redis加载的是 src/redis.c 文件的函数,而这两个文件的初始化函数,限定了只能使用哪些命令

数据结构

Sentinel 的结构体如下

typedef struct sentinelRedisInstance {int flags;      // 标识,记录实例类型char *name;     // 该实例名字char *runid;    // 实例的运行iduint64_t config_epoch;  // 配置纪元,用于实现故障转移sentinelAddr *addr; 	// 实例地址mstime_t last_pub_time;   // 上次我们通过 Pub/Sub 发送了 hello 的时间。 mstime_t last_hello_time; // 仅在设置 SRI_SENTINEL 时使用。上次我们发送hello的响应时间mstime_t last_master_down_reply_time; // SENTINEL is-master-down command.命令的最新响应时间// ... mstime_t down_after_period; // 实例无响应多少毫秒之后才会被判断为主观下线// ...// Master 配置unsigned int quorum;// 判断这个实例为客观下线锁需要支持的投票数量// ... // Slave 配置int slave_priority; /* Slave 优先级 */struct sentinelRedisInstance *master; /* Master instance if it's slave. */char *slave_master_host;    /* Master host as reported by INFO */int slave_master_port;      /* Master port as reported by INFO */int slave_master_link_status; /* Master link status as reported by INFO */unsigned long long slave_repl_offset; /* Slave 复制的偏移量. */// ...
} sentinelRedisInstance;

创建链接

初始化Sentinel的最后一步是创建连向被监控主服务器的网络连接,Sentinel 将成为主服务器的客户端,可以向主服务器发送命令,并且从命令回复中获取相关的信息。

对于每个被Sentinel 监视的主服务器来说,Sentinel会创建两个连接主服务器的异步网络连接:

  1. 命令连接,这个连接专门用于向主服务器发送命令,并接受命令回复。
  2. 订阅连接,这个连接专门用于订阅主服务器的 __sentinel__:hello 频道。

为什么会有两个连接?
在Redis目前的发布与订阅功能中,被i发送的信息都不会保存在Redis服务器里面,如果在信息发送时,想要接受信息的客户端不在线或者断线,那么这个客户端就会丢失这条信息。 因此为了不丢失__sentinel__:hello 频道的任何信息,Sentinel必须专门用一个连接来接受该频道的信息。
除了订阅频道之外,Sentinel还必须向主服务器发送命令,以此来与主服务器进行通信,所以Sentinel还必须向主服务器创建命令连接。

在这里插入图片描述

获取信息 INFO

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

一般INFO命令的回复有以下信息:

  • 从服务器的运行ID、角色role、优先级slave_priority、复制偏移量
  • 主服务器的IP地址 master_host 以及主服务器的端口号 master_port
  • 主从服务器的连接状态master_link_status

获取到这些信息之后,就会更新存储到Sentinel的结构体中。

在这里插入图片描述

但是当主服务器处于下线状态,或者Sentinel正在对主服务器和从服务器进行故障转移操作时,Sentinel 向从服务器发送INFO命令的频率将会变成每秒一次

发送命令

对于监视同一个主服务器和从服务器的多个Sentinel来说,他们会以每两秒一次的频率,通过被监视服务器的 __sentinel:hello__ 频道发送消息来响应其他sentinel宣告自己的存在。

PUBLISH __sentinel__:hello "<s_ip>,<s_port>,<s_runid>,<s_epoch>,<m_name>,<m_ip>,<m_port>,<m_epoch>"

这条命令向服务器的__sentinel__:hello频道发送一条信息,这些信息的组成如下:

  • s_ 开头的是sentinel本身的信息。
  • m_开头的是主服务器的信息。如果此sentinel监视的是主服务器,那么这个参数就是主服务器的参数,如果监视的是从服务器,那么就是这个从服务器正在所复制的主服务器。

接收命令

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

SUBSCRIBE __sentinel__:hello

也就是说对于每一个sentinel连接的服务器,sentinel既通过命令连接到服务器的__sentinel__:hello 频道发送信息,又通过订阅连接服务器的__sentinel__:hello频道接受消息。
在这里插入图片描述
那么对于监视同一个服务器的多个sentinel来说,一个sentinel发送的信息就会被其他sentinel接受到,因为是监听订阅了同一个服务器的__sentinel__:hello频道,所sentinel就会感知到其他sentinel的存在。并sentinel将会更新其他的sentinel信息到自己的sentinel字典中。

在这里插入图片描述

sentinel 之间的通信

从上面我们知道每个Sentinel也会从__sentinel:hello__ 频道中接收其他Sentinel发送来的信息,并根据这些信息为其他Sentinel创建实例结构和命令连接。
在这里插入图片描述

但是Sentinel 只会与主服务器和从服务器创建命令连接和订阅连接,Sentinel 和 Sentinel 之间则只创建命令连接。

为什么sentinel与sentinel之间不需要创建订阅连接呢?
首先我们要确定订阅连接是用来干嘛的,订阅连接是用来发现其他节点的而sentinel已经通过主服务器或者从服务器的频道信息来发现未知的sentinel,也就是说sentinel订阅了主/从服务器已经知道了其他的sentinel,就不需要再进行订阅连接其他的sentinel了,而相互已知的sentinel只需要使用命令连接来进行通信就够了。

主/客观下线

Sentinel 会以每秒一次的频率向实例,包括主服务器,从服务器,其他Sentinel发送 PING 命令,并根据实例对PING命令的回复判断实例是否在线,当一个实例在指定的时长中连续向Sentinel发送无效回复时,Sentinel就会判断为主观下线。

在这里插入图片描述
Sentinel1 将向 Sentinel2、server、slave1、slave2发送ping命令。sentinel2也会进行同样的操作。那么一般会得到以下两种情况的回复

  • 有效回复:返回 PONG、LOADING、MASTERDOWN 三个中的一个
  • 无效回复:非有效回复的内容,或者是指定时间内没有返回任何的回复,而这个指定时间的字段为down-after-milliseconds

当Sentinel讲一个主服务器判断为主观下线,他会向同样监视这个主服务器的其他 Sentinel 进行询问,如果有足够多的结点判定这个主服务器为主观下线,那么就状态改成客观下线,某个节点的状态改成客观下线之后,监视这个节点的各个sentinel就会协商选取一个leader sentinel节点,并且由领头的 leader sentinel 节点发起一次针对主服务器的故障转移。

这个选举的过程在这里就不过多介绍了。有点类似raft。后面有空再说明。

故障转移

在选举出leader sentinel节点之后的故障转移会做以下几件事情:

  1. 在已下线主服务器属下的所有从服务器里面,挑选出一个从服务器,并将其转化成主服务器
  2. 让已下线的主服务器属下的所有从服务器改成复制新的主服务器。
  3. 将已下线主服务器设置为新的从服务器

新的主服务器是如何挑选出来的呢?首先leader sentinel节点会将已下线主服务器的所有从服务器保存到一个列表,根据一些规则进行过滤:

  1. 删除已下线或者状态不正常的从服务器,保证列表中剩余的从服务器是正常的。
  2. 删除所有最近5秒内没有回复leader sentinel节点的INFO命令的从服务器,保证列表中的从服务器都是最新通信成功的
  3. 删除与已下线的主服务器连接断开超过 down-after-milliseconds * 10 毫秒的从服务器,保证剩余的服务器保存的数据都是比较新

down-after-milliseconds:实例失去联系的时间,而删除断开这个时间的10倍,是为了能保证剩余的从服务器没有过早的与主服务器断开连接。

  1. 会根据从服务器的优先级进行排序,选择最高优先级的从服务器,如果相同优先级,则选择偏移量最大服务器。因为偏移量大意味着数据最新。

易主

选择完主服务器之后,就开始改变从服务器的复制对象了。这一动作可以通过向服务器发送SLAVEOF的命令来实现。
在这里插入图片描述

本文我们详细介绍了redis集群中sentinel的数据结构,sentinel与主从服务器的连接,信息传递,以及主从服务器发生故障时的处理方式。

那么问题来了?如果sentinel 集群中某一个sentinel节点挂了会发送什么事情呢?

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/319533.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

如何配置X86应用程序启用大地址模式(将用户态虚拟内存从2GB扩充到3GB),以解决用户态虚拟内存不够用问题?(项目实战案例解析)

目录 1、概述 2、为什么不直接将程序做成64位的&#xff1f; 3、进程内存不足导致程序发生闪退的案例分析 3.1、问题说明 3.2、将Windbg附加到程序进程上进行动态调试 3.3、动态调试的Windbg感知到了中断&#xff0c;中断在DebugBreak函数调用上 3.4、malloc或new失败的…

正点原子[第二期]Linux之ARM(MX6U)裸机篇学习笔记-6.5--I.MX6U启动方式

前言&#xff1a; 本文是根据哔哩哔哩网站上“正点原子[第二期]Linux之ARM&#xff08;MX6U&#xff09;裸机篇”视频的学习笔记&#xff0c;在这里会记录下正点原子 I.MX6ULL 开发板的配套视频教程所作的实验和学习笔记内容。本文大量引用了正点原子教学视频和链接中的内容。…

Unity开发微信小游戏(2)分享

目录 1.概述 2.代码 3.示例 4.个人作品 1.概述 这里我们能做有两件事&#xff1a; 1&#xff09;主动发起分享 2&#xff09;监听右上角分享&#xff08;...按钮&#xff0c;发朋友圈也在这里&#xff09; API&#xff1a;官方文档 2.代码 1&#xff09;主动发起分享&…

【Linux】进程程序替换

思维导图 学习目标 学习进程替换的原理&#xff0c;掌握一些exec*函数的用法。 一、进程的程序替换的原理 用fork创建子进程后&#xff0c;子进程执行的是和父进程相同的程序&#xff08;但有可能执行不同的代码分支&#xff09;&#xff0c;若想让子进程执行另一个程序&#…

Liunx发布tomcat项目

Liunx在Tomcat发布JavaWeb项目 1.问题2.下载JDK3.下载Tomcat4.Tomcat本地JavaWeb项目打war包、解压、发布5.重启Tomcat,查看项目 1.问题 1.JDK 与 Tomcat 版本需匹配&#xff0c;否则页面不能正确显示 报错相关&#xff1a;Caused by: java.lang.ClassNotFoundException: java…

贪吃蛇(上)Win32API

感谢大佬的光临各位&#xff0c;希望和大家一起进步&#xff0c;望得到你的三连&#xff0c;互三支持&#xff0c;一起进步 个人主页&#xff1a;LaNzikinh-CSDN博客 文章目录 前言一、Win32 API二、地图的绘制和初始化总结 前言 贪吃蛇&#xff08;也叫做贪食蛇&#xff09;游…

深入学习Redis(1):Redis内存模型

Redis的五个对象类型 字符串&#xff0c;哈希&#xff0c;列表&#xff0c;集合&#xff0c;有序集合 本节有关redis的内存模型 1.估算redis的内存使用情况 目前内存的价格比较的高&#xff0c;如果对于redis的内存使用情况能够进行计算&#xff0c;就可以选用合适的设备进…

基于MSOGI的交叉对消谐波信号提取网络MATLAB仿真

微❤关注“电气仔推送”获得资料&#xff08;专享优惠&#xff09; 模型简介&#xff1a; 此模型利用二阶广义积分器&#xff08;SOGI&#xff09;对基波电流和相应次的谐波电流进行取 &#xff0c;具体是通过多个基于二阶广义积分器的正交信号发生器 &#xff08; S&#xf…

JavaScript入门:用JS点亮你的第 1 个网页圣诞树!

你好&#xff0c;我是云桃桃。 一个希望帮助更多朋友快速入门 WEB 前端的程序媛。 云桃桃-大专生&#xff0c;一枚程序媛&#xff0c;感谢关注。回复 “前端基础题”&#xff0c;可免费获得前端基础 100 题汇总&#xff0c;回复 “前端工具”&#xff0c;可获取 Web 开发工具合…

JVM笔记1--Java内存区域

1、运行时数据区域 从上图可以看出来&#xff0c;Java虚拟机运行时数据区域整体上可以分成5大块&#xff1a; 1.1、程序计数器 程序计数器是一块较小的内存空间。它可以看做当前线程所执行的字节码的行号指示器。在Java虚拟机的概念模型里&#xff0c;字节码解释器工作时就是…

vue实现滚动条联动(一个滚动条控制两个或多个)

两个表格需要进行比对&#xff0c;两个表格是互相独立的&#xff0c;如果滚动条不能同步&#xff0c;用户就要操作两个两次&#xff0c;体验不是太好&#xff0c;如下图&#xff1a; 因此想使两个滚动条同步&#xff0c;思路如下&#xff1a; 给两个表格定义ref&#xff08;便…

环形链表的判断方法与原理证明

&#xff08;题目来源&#xff1a;力扣&#xff09; 一.判读一个链表是否是环形链表 题目&#xff1a; 解答&#xff1a; 方法&#xff1a;快慢指针法 内容&#xff1a;分别定义快慢指针&#xff08;fast和slow&#xff09;&#xff0c;快指针一次走两步&#xff0c;慢指…

机器学习的指标评价

之前在学校的小发明制作中&#xff0c;在终期答辩的时候&#xff0c;虽然整个项目的流程都答的很流畅。 在老师提问的过程中&#xff0c;当老师问我recall,precision,accuracy等指标是如何计算的&#xff0c;又能够表示模型的哪方面指标做得好。我听到这个问题的时候&#xff…

如何选购骨传导耳机?精选五大拔尖宝藏骨传导耳机,闭眼入也不踩雷!

尽管目前市面上的骨传导耳机热度非常高&#xff0c;一度成为当下最热门的耳机款式&#xff0c;但作为有着资深工作经验的数码测评师&#xff0c;我仍然要提醒大家&#xff1a;在选择骨传导耳机的时候&#xff0c;不要盲目选择网红品牌&#xff0c;因为市场上的许多骨传导耳机过…

用LM Studio搭建微软的PHI3小型语言模型

什么是 Microsoft Phi-3 小语言模型&#xff1f; 微软Phi-3 模型是目前功能最强大、最具成本效益的小型语言模型 &#xff08;SLM&#xff09;&#xff0c;在各种语言、推理、编码和数学基准测试中优于相同大小和更高大小的模型。此版本扩展了客户高质量模型的选择范围&#x…

golang判断通道chan是否关闭的2种方式

chan通道在go语言的办法编程中使用频繁&#xff0c;我们可以通过以下2种方式来判断channel通道是否已经关闭&#xff0c;1是使用 for range循环&#xff0c;另外是通过 for循环中if 简短语句的 逗号 ok 模式来判断。 示例代码如下&#xff1a; //方式1 通过for range形式判断…

现代循环神经网络(GRU、LSTM)(Pytorch 14)

一 简介 前一章中我们介绍了循环神经网络的基础知识&#xff0c;这种网络 可以更好地处理序列数据。我们在文本数据上实现 了基于循环神经网络的语言模型&#xff0c;但是对于当今各种各样的序列学习问题&#xff0c;这些技术可能并不够用。 例如&#xff0c;循环神经网络在…

centos7 openresty lua 自适应webp和缩放图片

目录 背景效果图准备安装cwebp等命令&#xff0c;转换文件格式安装ImageMagick&#xff0c;压缩文件下载Lua API 操控ImageMagick的依赖包 代码参考 背景 缩小图片体积&#xff0c;提升加载速度&#xff0c;节省流量。 效果图 参数格式 &#xff1a; ?image_processformat,…

PyVista 3D数据可视化 Python 库 简介 含源码

Pyvista是一个用于科学可视化和分析的Python库 &#xff1b;我认为它适合做一些网格数据的处理&#xff1b; 它封装了VTK&#xff08;Visualization Toolkit&#xff09;之上&#xff0c;提供了一些高级接口&#xff0c; 3D数据可视化变得更加简单和易用。 1.安装 pyvista&…

蓝桥杯-路径之谜

题目描述 小明冒充X星球的骑士&#xff0c;进入了一个奇怪的城堡。城堡里面什么都没有&#xff0c;只有方形石头铺成的地面。 假设城堡的地面时n*n个方格。如下图所示。 按习俗&#xff0c;骑士要从西北角走到东南角。可以横向或者纵向移动&#xff0c;但是不能斜着走&#x…