Redis哨兵模式高可用原理

2023-10-27

我们知道主从复制是高可用的基石,从库宕机依然可以将请求发送给主库或者其他从库,但是 Master 宕机,只能响应读操作,写请求无法再执行。

所以主从复制架构面临一个严峻问题,主库挂了,无法执行「写操作」,无法自动选择一个 Slave 切换为 Master,也就是无法故障自动切换。

什么是哨兵(Sentinel)

搭建实例采用三个哨兵形成集群,三个数据节点(一主两从)方式搭建,如下图所示:

哨兵机制的主要任务

哨兵是 Redis 的一种运行模式,它专注于对 Redis 实例(主节点、从节点)运行状态的监控,并能够在主节点发生故障时通过一系列的机制实现选主及主从切换,实现故障转移,确保整个 Redis 系统的可用性。结合 Redis 的 官方文档:https://redis.io/topics/sentinel,可以知道 Redis 哨兵具备的能力有如下几个:

  • 监控:持续监控 master 、slave 是否处于预期工作状态。
  • 自动切换主库:当 Master 运行故障,哨兵启动自动故障恢复流程:从 slave 中选择一台作为新 master。
  • 通知:让 slave 执行 replicaof ,与新的 master 同步;并且通知客户端与新 master 建立连接。
监控

在默认情况下,Sentinel 通过以每秒一次的频率向所有包括 Master、Slave、其他 Sentinel 在内)发送 PING 命令,如果 slave 没有在在规定时间内响应「哨兵」的 PING 命令,「哨兵」就认为这哥们可能嗝屁了,就会将他记录为「下线状态」;

假如 master 没有在规定时间响应 「哨兵」的 PING 命令,哨兵就判定master下线,开始执行「自动切换 master 」的流程。

PING 命令的回复有两种情况:

有效回复:返回 +PONG、-LOADING、-MASTERDOWN 任何一种;
无效回复:有效回复之外的回复,或者指定时间内返回任何回复。

为了防止master「假死」,「哨兵」设计了「主观下线」和「客观下线」两种暗号。

主观下线
哨兵利用 PING 命令来检测master、 slave 的生命状态。如果是无效回复,哨兵就把这个哥们标记为「主观下线」。

因为有可能出现误判,master并没有嗝屁,一旦启动了master切换,后续的选主、通知,slave 花时间与新 master 同步数据都会消耗大量资源。

所以「哨兵」要降低误判的概率,误判一般会发生在集群网络压力较大、网络拥塞,或者是主库本身压力较大的情况下。

既然一个人容易误判,那就多个人一起投票判断。哨兵机制也是类似的,采用多实例组成的集群模式进行部署,这就是哨兵集群。引入多个哨兵实例一起来判断,就可以避免单个哨兵因为自身网络状况不好,而误判主库下线的情况。

同时,多个哨兵的网络同时不稳定的概率较小,由它们一起做决策,误判率也能降低。

客观下线
判断 master 是否下线不能只有一个「哨兵」说了算,只有过半的哨兵判断 master 已经「主观下线」,这时候才能将 master 标记为「客观下线」,也就是说这是一个客观事实。

主观下线与客观下线的区别
简单来说,主观下线是哨兵自己认为节点宕机,而客观下线是不但哨兵自己认为节点宕机,而且该哨兵与其他哨兵沟通后,达到一定数量的哨兵都认为该哥们嗝屁了。

这里的「一定数量」是一个法定数量(Quorum),是由哨兵监控配置决定的,解释一下该配置:

这条配置项用于告知哨兵需要监听的主节点:

  • sentinel monitor:代表监控。
  • mymaster:代表主节点的名称,可以自定义。
  • 192.168.11.128:代表监控的主节点 ip,6379 代表端口。
  • 2:法定数量,代表只有两个或两个以上的哨兵认为主节点不可用的时候,才会把 master 设置为客观下线状态,然后进行 failover 操作。

「客观下线」的标准就是,当有 N 个哨兵实例时,要有 N/2 + 1 个实例判断 master 为「主观下线」,才能最终判定 Master 为「客观下线」,其实就是过半机制。

自动切换主库

「哨兵」的第二个任务,选择新 master 。按照一定的 「筛选条件」 + 「打分」 策略,将得分最高者选为新 master。

筛选条件
  • 从库当前在线状态,下线的直接丢弃;
  • 评估之前的网络连接状态 down-after-milliseconds * 10:如果从库总是和主库断连,而且断连次数超出了一定的阈值(10 次),我们就有理由相信,这个从库的网络状况并不是太好,就可以把这个从库筛掉了。

打分
过滤掉不合适的 slave 之后,则进入打分环节。打分会按照三个规则进行三轮打分,规则分别为:
1、slave 优先级,通过 slave-priority 配置项,给不同的从库设置不同优先级(后台有人没办法),优先级高的直接晋级为新 master 。
2、slave_repl_offset与 master_repl_offset进度差距,如果都一样,那就继续下一个规则。其实就是比较 slave 与旧 master 复制进度的差距;
3、slave runID,在优先级和复制进度都相同的情况下,ID 号最小的从库得分最高,会被选为新主库。(论资排辈,根据 runID 的创建时间来判断,时间早的上位);

通知

哨兵集群工作原理

「哨兵」并不是一个人,多个人共同组成一个「哨兵集群」,即使有一些「哨兵」被老王打死了,其他的「哨兵」依然可以共同协作完成监控、选举以及通知 slave 、master 以及客户端。

在配置哨兵集群的时候,哨兵配置中只设置了监控的 master IP 和 port,并没有配置其他哨兵的连接信息。

哨兵之间是如何知道彼此的?如何知道 slave 并监控他们的?由哪一个「哨兵」执行主从切换呢?

pub/sub 实现哨兵间通信和发现 slave

哨兵之间可以相互通信搞事情,主要归功于 Redis 的 pub/sub 发布/订阅机制。

哨兵与 master 建立通信,利用 master 提供发布/订阅机制发布自己的信息,比如身高体重、是否单身、IP、端口……

master 有一个 sentinel:hello 的专用通道,用于哨兵之间发布和订阅消息。这就好比是 sentinel:hello 微信群,哨兵利用 master 建立的微信群发布自己的消息,同时关注其他哨兵发布的消息。

当多个哨兵实例都在主库上做了发布和订阅操作后,它们之间就能知道彼此的 IP 地址和端口,从而相互发现建立连接。

Redis 通过频道的方式对消息进行分别管理,这里的频道其实就是不同的微信群。

哨兵之间虽然建立连接了,但是还需要和 slave 建立连接,不然没法监控他们呀,如何知道 slave 并监控他们的?

关键还是利用 master 来实现,哨兵向 master 发送 INFO 命令, master 自然是知道所有的 salve的。所以 master 接收到命令后,便将 slave 列表告诉哨兵。

哨兵根据 master 响应的 slave 名单信息与每一个 salve 建立连接,并且根据这个连接持续监控哨兵。

选择哨兵执行主从切换

这个跟哨兵判断 master “客观下线”类似,也是通过投票的方式选出来的。

任何一个哨兵判断 master “主观下线”后,就会给其他哨兵基友发送 is-master-down-by-addr 命令,好基友则根据自己跟 master 之间的连接状况分别响应 Y 或者 N ,Y 表示赞成票, N 就是反对。

如果某个哨兵获得了大多数哨兵的“赞成票”之后,就可以标记 master 为 “客观下线”,赞成票数是通过哨兵配置文件中的 quorum 配置项设定。

获得多数赞成票的哨兵可以向其他哨兵发送命令,申明自己想要执行主从切换。并让其他哨兵进行投票,投票过程就叫做 “Leader 选举”。

想要成为 “Leader”没那么简单,得有两把刷子。需要满足以下条件:

1、获得其他哨兵基友过半的赞成票;
2、赞成票的数量还要大于等于配置文件的 quorum 的值。

通过 pub/sub 实现客户端事件通知

新 master 选出来了,要怎么公示天下呢?

在 Redis 也是类似,通过 pub/sub 机制发布不同事件,让客户端在这里订阅消息。客户端可以订阅哨兵的消息,哨兵提供的消息订阅频道有很多,不同频道包含了主从库切换过程中的不同关键事件。

也就是在不同的“微信群”发布不同的事件,让对该事件感兴趣的人进群即可。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Redis哨兵模式高可用原理 的相关文章

  • 使用 Java 编辑 jpeg EXIF 数据

    我想编辑 jpg 文件的属性 例如 评论 标题 拍摄日期 相机制造商等 我找到了读取这些数据的库 但我需要一个free带有示例的库edit them 我知道 apache 的成像 sanselan 但我无法用它编辑数据 如果您以前自己使用过
  • 如何从二维数组中仅打印单个列?

    我正在编写这个程序 我必须只打印二维数组的一列 而不是两者 for int i 0 i lt sjf length i for int j 0 j lt sjf i length j System out printf 5d 4s sjf
  • 使用 REST API 实现属性/字段级安全

    我正在为支持多租户授权模型的 REST API 构建概念验证 该模型不仅控制用户可以访问哪些对象 还控制对象中的字段 此模型的目标是确保租户管理员只能修改其租户并且只能查看允许的对象属性 我有一个正在开发的现有代码库 可在以下位置公开获取
  • Zuul不转发请求到其他微服务

    我正在使用 Spring Boot 微服务 我已经配置了 eureka zuul 代理和另一个微服务 帐户 如果我直接从帐户拨打电话 则工作正常 帐户和 zuul 服务器都显示在 eureka 上 当我尝试使用 zuul 代理进行访问时 它
  • Java 访问被拒绝

    C Program Files x86 Java jdk1 6 0 17 bin gt javac VendingMachine java VendingMachine java 27 error while writing Vending
  • Android - 检测电容式触摸屏上的触摸压力?

    我听说过 MotionEvent e float press e getPressure 但这只会在没有触摸时返回 0 当我的手指触摸屏幕时返回 1 是否可以找到手指在触摸电容屏上施加的压力值 或者我的预感是否正确 即这只适用于电阻屏幕 M
  • Java 区域设置区分大小写

    我有以下代码来显示当前区域设置 System out println Locale getDefault System out println new Locale en US 上面给出的输出如下 en US en us 如何构造一个 Lo
  • Jersey 客户端异步 POST 请求不等待响应

    我创建了一个简单的 Jersey 客户端 它能够成功地使用有效负载执行 POST 请求 但现在它正在等待来自 http 端点的响应 public void callEndpoint String endpoint String payloa
  • 请放心,如何在 POST 请求后从响应正文中提取生成的令牌并将其设置到标头

    执行任何请求 我需要执行身份验证POST请求正文 username somename password somepass 标头Content Type application json这给了我一个带有生成令牌的响应 我需要将其粘贴为第二个标
  • Java Swing 自定义形状(2D 图形)

    我需要绘制自定义形状 现在 当用户单击面板上的几个点时 我使用多边形创建一个形状 public void mouseClicked MouseEvent e polygon addPoint e getX e getY repaint 但我
  • 创建UML图时应该编写构造函数吗?

    我有一项作业要求我为实际的 Java 程序创建 UML 图 但程序中有几个构造函数方法 我很困惑 我是否应该将这些构造函数方法添加到图中 根据 UML 规范 2 5 版第 11 4 4 节 构造函数是一个具有所属类类型的单个返回结果参数的操
  • 如何用Java捕获音频数据

    我想访问我的麦克风用 Java 录制的音频数据 我该怎么做呢 我的目标是保存录制的音频数据并同时向用户播放 如果您不需要 JMF 中的任何附加功能 我会避免使用它 因为开发已经停止 最后一个版本是 2004 年 它与 Java 6 存在兼容
  • Java DocumentBuilder - XML 文件中的缩进错误

    我尝试使用 DocumentBuilder 用 Ja va 编写一个简单的 XML 文件 我期望 XML 文件如下所示
  • 使用 JNDI 添加 LDAP 条目

    我正在尝试使用 JNDI 将条目添加到 LDAP 服务器 我可以成功地从 LDAP 服务器读取条目 但是当我尝试添加新条目时出现错误 我检查了各种方法但都失败了 private String getUserAttribs String se
  • 使用 GSON 将 JSON 字符串转换为 Java 对象

    我正在尝试将 json 解析为 java 根据 jsonlint com 我有以下字符串 该字符串是有效的 json private final static String LOC JSON lat1 39 737567 lat2 32 7
  • 从 Apache Kafka 中的主题删除消息

    所以我是 Apache Kafka 的新手 我正在尝试创建一个简单的应用程序 以便我可以更好地理解 API 我知道这个问题在这里被问了很多 但是如何清除存储在主题上的消息 记录 我看到的大多数答案都说要更改消息保留时间或删除并重新创建主题
  • Java 需要一个 FileSet 包/类

    任何人都可以建议 Java 中的 FileSet 包 类吗 我所说的 FileSet 是指文件和目录的集合以及正则表达式支持的包含和排除规则 类似于 Apache Ant 谢谢 Apache 公共 IO文件工具 http commons a
  • Spring MVC 和复选框

    我正在使用 Spring MVC 3 0 并且不能完全看到这个问题的所有部分 我的控制器将生成一个域对象列表 假设有一个简单的 User 对象 具有firstName lastName age 和role 属性 我想在表中输出该用户列表 每
  • 无法以联觉方式绘制像素、Pi 数

    我想将 pi 数字的每个数字打印为彩色像素 因此 我得到一个带有 pi 数字的输入 然后将其解析为一个列表 每个节点包含一个数字 我知道 稍后我将使用一个数组 但我从来没有把它画到屏幕上 有人能帮我看看我错在哪里吗 import java
  • JVM锯齿状空闲进程

    我目前正在进行一项涉及 JVM 及其内存使用工作原理的研究 我不明白的是 JVM在空闲时用什么填充它的内存 只是为了在堆几乎达到时释放它 为什么使用的内存不只有一条平线 顺便说一句 这个 java 应用程序托管在 glassfish 上 但

随机推荐

  • 漏洞扫描器 XRAY

    文章目录 XRAY简介 XRAY安装 XRAY使用 爬虫模式 被动扫描 生成 ca 证书 开启监听 浏览器设置代理 访问网站自动探测漏洞 BurpSuite联动XRAY xray 开启端口监听 burpsuite 设置 通过burp sui
  • js 实现汉字简体和繁体之间的互相转换

    简体字 简体字 Simplified Chinese 简体中文 是中国大陆地区目前在用的字体 由官方公布的简体字 主要由传承字以及1950年代以后中华人民共和国政府开始在中国大陆地区推行的简化字所组成 目前 简体字的使用地区包括中国大陆 联
  • C++ 保存txt文本文件

    第一步 包含头文件 include
  • ExtJS 容器布局方式

    ExtJS是构建浏览器应用界面的框架 为开发人员提供了丰富UI组件 这些组件在页面中是以特定方式排列的 即布局方式 一个ExtJS构建的页面 无论看起来多么复杂 最终都能根据其布局拆分成许多小的区域 最近工作中的项目比较老旧 使用的是3 0
  • vue子组件向父组件传值的方法

    子组件向父组件 使用 emit方法 demo 子组件的代码
  • 【手把手 带你准备电赛】解答小课堂——串口通信和串行通信

    目录 串口通信和串行通信的定义 串口通信和串行通信的区别 串口通信和串行通信的联系 串口 串行 你分清楚这两个概念了吗 是不是还是串什么通信 串行通信 什么串口 不要担心 这篇文章 小蛋糕带你深入浅出分清串口通信和串行通信 串口通信和串行通
  • k线图中趋势线的画法精讲

    曾经有技术分析师大师把技术分析概括为一句话 那就是 一把直尺走天下 这是画线分析方法的直观和有效的高度概括 在众多的画线方法中 趋势线用以衡量贵金属的价格趋势 通过趋势线的方向可以明确地看出价格变动的方向 一 上升趋势线的画法 在上升趋势中
  • Ubuntu下pycharm的安装和卸载

    pycahrm安装 首先要去pycharm的官方网站下载Linux版本的pycharm安装包 如果想要下载以前版本的pycharm可以登录下方的网站去下载 https www jetbrains com pycharm download o
  • 按摩软件仿东郊到家系统开发,上门预约系统;

    按摩软件仿东郊到家系统开发 上门预约系统 用户端 技师端 商家端 以及管理后台 上门预约的操作 1 技师管理 技师满意度进行统一跟踪评估 进行分级管理 分级评估 2 订单管理 按订单状态分类筛选 安装进度一目了然 3 智能派单 根据客户位置
  • 64位机器源码安装遇到的问题,解决,一锅端

    1 如果是centos5会出现如下问题 checking host system type Invalid configuration x86 64 unknown linux gnu machine x86 64 unknown not
  • Hexo-零基础搭建个人博客(详解)

    Hexo零基础搭建个人博客 Hexo是一个基于 node js的快速生成静态博客的开源框架 支持 Markdown和大多数 Octopress 插件 一个命令即可部署到 Github页面 Giteee Heroku等 强大的APl 可无限扩
  • 数据库关闭四种方式

    数据库关闭四种方式 shutdown 参数 默认normal abort 模拟突然掉电 内存被清空 内存中的数据没有写入数据文件 事务被立即中断 没有提交也没有回滚 immediate 强制中断当前正在运行的所有事务 回滚这些事务 回滚完毕
  • c语言编写简易的自动售货机程序

    今天本来想做一个弹窗的可以输入有按钮点确定的自动售货机程序的 但是因为学校没教我是自学的找了一下午 不是教我如何创建的 就是代码各种报错的 我试了一下午都不行 只能放弃了 今天这串代码是根据我的c语言笔试 我们有上机考试的 的其中一道编程的
  • 二、量化选股

    文章目录 总体介绍 一 基本面选股 1 因子选股 判断方法 五个步骤 2 风格轮动 3 行业轮动 二 市场行为选股 1 资金流 2 动量反转 基本概念 1 行为金融学 2 阿尔法动量模型 3 一致预期 4 趋势追踪 基本概念 5 筹码选股
  • uniGUI用Grid++Report报表插件设计保存报表(For unigui ver:0.95.0.1045)

    uniGUI的0 95 0 1045版本提供了CallbackUrl 我们也可以用这个提供的回调网址来实现优秀的国产报表插件在IE Chorme FireFox中在线设计并保存报表到服务端的功能 界面效果如下 代码如下 unit Main
  • SpringBoot用线程池ThreadPoolExecutor处理百万级数据

    SpringBoot用线程池ThreadPoolExecutor处理百万级数据 更多优秀文章 请扫码关注个人微信公众号或搜索 程序猿小杨 添加 一 背景 使用JDK线程池ThreadPoolExecutor多线程异步执行批量插入 更新等操作
  • 如何优雅地用VScode在Ubuntu服务器上跑cuda代码

    0 安装相关软件 VScode 及对应插件 推荐VScode配置好远程服务后在服务端添加如下插件 Xming Xming X Server for Windows download SourceForge netDownload Xming
  • CMake Error: CMake was unable to find a build program corresponding to “Ninja“.

    CMake Error CMake was unable to find a build program corresponding to Ninja 使用cmake G ninja 后出现问题 报错信息如下所示 CMake Error C
  • 关于dispose 方法的资源释放

    当在程序上实现dispose 方法时 当前对象所占用的资源会被释放 当前对象便不能再被使用 但在内存中还并不会被及时的释放 要待到下次垃圾回收的时候 内存才能得到释放
  • Redis哨兵模式高可用原理

    我们知道主从复制是高可用的基石 从库宕机依然可以将请求发送给主库或者其他从库 但是 Master 宕机 只能响应读操作 写请求无法再执行 所以主从复制架构面临一个严峻问题 主库挂了 无法执行 写操作 无法自动选择一个 Slave 切换为 M