redis 高可用 Sentinel 详解

news2024/11/16 18:53:12

写在前面

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;    // 实例的运行id
    uint64_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.coloradmin.cn/o/1637885.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

图床搭建GitHub+PicGo+jsdelivr(CDN)+Typora(内附加速工具)

目录 安装PicGo GitHub配置与加速器 配置PicGo 使用typroa 安装PicGo PicGo是一个用于上传图片的客户端&#xff0c;支持拖拽上传、剪贴板上传&#xff0c;功能十分方便。 下载地址&#xff1a; https://github.com/Molunerfinn/PicGo/releases 个人网盘自取版本2.4.0…

C++成员初始化列表

我们在类的构造函数中使用成员初始化列表可以带来效率上的提升&#xff0c;那么成员初始化列表在编译后会发生什么就是这篇文章要探究的问题 文章目录 引入成员初始化列表用成员初始化列表优化上面的代码成员初始化列表展开成员初始化列表的潜在危险 参考资料 引入 考虑下面这…

CSS高级选择器

一、属性选择器 以value开头的att属性的E元素&#xff1a;E[att^"value"]{ ;} a[href^http]{background-color"red";} css a[href^http]{background-color"red"; } html <!DOCTYPE html> <html lang"en"> <head&…

特斯拉全自动驾驶系统Tesla‘s Full-Self Driving (FSD)

版权声明 本文原创作者&#xff1a;谷哥的小弟作者博客地址&#xff1a;http://blog.csdn.net/lfdfhl Overview Tesla’s FSD is a suite of features that includes Autopilot, Navigate on Autopilot, Auto Lane Change, Autopark, Summon, and Traffic Light and Stop Sig…

数字旅游引领未来智慧之旅:科技应用深度重塑旅游生态,智慧服务全面升级打造极致高品质旅游体验

随着信息技术的飞速发展&#xff0c;数字旅游作为旅游业与科技融合的新兴业态&#xff0c;正以其独特的魅力和优势&#xff0c;引领着旅游业迈向智慧之旅的新时代。数字旅游不仅通过科技应用重塑了旅游生态&#xff0c;更通过智慧服务为游客带来了高品质的旅游体验。本文将深入…

C语言嵌入Lua解释器的方法

Lua语言是一个轻量的脚本语言&#xff0c;可以用很少的资源运行其解释器 C语言是一个很常用的语言&#xff0c;广泛用于嵌入式等底层场景 这两个语言结合&#xff0c;可以应用于嵌入式等多个场景。比如&#xff0c;一些硬件公司会允许开发者使用Lua语言操作其硬件 Lua的安装…

PySpark学习---销售情况数据统计分析案例

需求分析&#xff1a; 某公司是做零售相关业务&#xff0c;旗下出品各类收银机. 目前公司的收银机已经在全国铺开,在各个省份均有店铺使用.机器是联网的,每一次使用都会将售卖商品数据上传到公司后台.老板现在想对省份维度的销售情况进行统计分析 逻辑需求&#xff1a; 1.各省销…

APScheduler定时器使用:django中使用apscheduler,使用mysql做存储后端

一、基本环境 python版本&#xff1a;3.8.5 APScheduler3.10.4 Django3.2.7 djangorestframework3.15.1 SQLAlchemy2.0.29 PyMySQL1.1.0二、django基本设置 2.1、新增一个app 该app用来写apscheduler相关的代码 python manage.py startapp gs_scheduler 2.2、修改配置文件s…

Qt在任务栏图标和系统托盘图标上显示红点

在任务栏图标上显示红点 关键类&#xff1a;QWinTaskbarButton #include <QWinTaskbarButton>QPointer<QWinTaskbarButton> taskbarBtn nullptr; if (!taskbarBtn) {taskbarBtn new QWinTaskbarButton(window);taskbarBtn->setWindow(window->windowHand…

重定义大语言模型的记忆能力:对抗性压缩如何挑战现有测量法

DeepVisionary 每日深度学习前沿科技推送&顶会论文分享&#xff0c;与你一起了解前沿深度学习信息&#xff01; Rethinking LLM Memorization through the Lens of Adversarial Compression 引言&#xff1a;探索大型语言模型的记忆能力 在当今信息时代&#xff0c;大型…

ROS1快速入门学习笔记 - 11参数的使用与编程方法

目录 一、参数模型&#xff08;全局字典&#xff09; 二、使用方法 1. 创建功能包 2. 参数命令行的使用 3. 通过C实现参数设置 4. 在CMakeLists中进行编译 5. 运行程序 6. 编程方法&#xff08;Python&#xff09; 一、参数模型&#xff08;全局字典&#xff09; 每个节…

2024.5.5 机器学习周报

引言 Abstract 文献阅读 1、题目 SuperGlue: Learning Feature Matching with Graph Neural Networks 2、引言 本文介绍了SuperGlue&#xff0c;这是一种神经网络&#xff0c;它通过联合寻找对应关系并拒绝不匹配的点来匹配两组局部特征。通过求解一个可微的最优运输问题…

【PCL】教程 example2 3D点云之间的精确配准(FPFH特征对应关系估计变换矩阵)

这段代码主要实现了点云之间的配准功能&#xff0c;旨在通过估计点云的特征并找到最佳的对应关系来计算一个变换矩阵&#xff0c;从而可以将源点云&#xff08;src&#xff09;变换到目标点云&#xff08;tgt&#xff09;的坐标系统中。 代码功能和方法总结如下&#xff1a; 估…

STM32 DMA直接存储器存取

单片机学习&#xff01; 目录 文章目录 前言 一、DMA简介 1.1 DMA是什么 1.2 DMA作用 1.3 DMA通道 1.4 软硬件触发 1.5 芯片资源 二、存储器映像 2.1 存储器 2.2 STM32存储器 三、DMA框图 3.1 内核与存储器 3.2 寄存器 3.3 DMA数据转运 3.4 DMA总线作用 3.5 DMA请求 3.6 DMA结构…

Flutter笔记:Widgets Easier组件库(3)使用按钮组件

Flutter笔记 Widgets Easier组件库&#xff08;3&#xff09;&#xff1a;使用按钮组件 - 文章信息 - Author: 李俊才 (jcLee95) Visit me at CSDN: https://jclee95.blog.csdn.netMy WebSite&#xff1a;http://thispage.tech/Email: 291148484163.com. Shenzhen ChinaAddre…

数字旅游以科技创新为核心:推动旅游服务的智能化、精准化、个性化,为游客提供更加贴心、专业、高效的旅游服务

目录 一、引言 二、数字旅游以科技创新推动旅游服务智能化 1、智能化技术的应用 2、提升旅游服务的效率和质量 三、数字旅游以科技创新推动旅游服务精准化 1、精准化需求的识别与满足 2、精准化营销与推广 四、数字旅游以科技创新推动旅游服务个性化 1、个性化服务的创…

Cloudflare高级防御规则 看看我的网站如何用防御的

网站已趋于稳定&#xff0c;并且经过nginx调优。我想先分享一下Cloudflare的WAF规则&#xff0c;因为这是最有效的防御之一&#xff0c;可以抵御大量恶意攻击流量&#xff0c;我已经验证了数月。 对于海外独立站电商网站&#xff0c;Cloudflare的CDN服务是首选&#xff0c;它强…

File contains parsing errors: file:///etc/yum.repos.d/nginx.repo报错解决,文件配置出现问题

执行yum指令出现以下错误&#xff1a; 解决方案&#xff1a;yum的配置文件出现问题&#xff0c; 先删除yum.repos.d目录下所有文件 rm -f /etc/yum.repos.d/* 然后重新下载阿里的资源 wget -O /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/repo/Centos-7.…

VPX双路***至强高性能服务器模块

VPX双路***至强高性能服务器模块 1 产品介绍 1.1 产品概述 是一款基于Intel Xeon Gold系列处理器设计的双至强VPX模块&#xff0c;连接器采用VPX规范的高速连接器&#xff0c;专为高性能全加固服务器设计&#xff0c;具有贴片内存颗粒128GB DDR4内存&#xff0c;并提供了丰富…

翻译: 什么是ChatGPT 通过图形化的方式来理解 Transformer 架构 深度学习三

合集 ChatGPT 通过图形化的方式来理解 Transformer 架构 翻译: 什么是ChatGPT 通过图形化的方式来理解 Transformer 架构 深度学习一翻译: 什么是ChatGPT 通过图形化的方式来理解 Transformer 架构 深度学习二翻译: 什么是ChatGPT 通过图形化的方式来理解 Transformer 架构 深…