当前位置: 首页 > news >正文

Redis:分布式 - 哨兵

Redis:分布式 - 哨兵

    • 概念
      • 哨兵
    • Docker 搭建哨兵分布式
    • 选举
      • 流程


概念

Redis 的主从复制模式下,一旦主节点由于故障不能提供服务,需要人工进行主从切换,同时大量的客户端需要被通知切换到新的主节点上,对于上了一定规模的应用来说,这种方案是无法接受的,于是 Redis 2.8 开始提供了 Redis Sentinel(哨兵)来解决这个问题。

由于对 Redis 的许多概念都有不同的名词解释,所以在介绍 Redis Sentinel之前,先对几个名词概念进行必要的说明,如表所示。

名词逻辑结构物理结构
主节点Redis主服务一个独立的redis-server进程
从节点Redis从服务一个独立的redis-server进程
Redis数据节点主从节点主节点和从节点的进程
哨兵节点监控Redis数据节点的节点一个独立的redis-sentinel进程
哨兵节点集合若干哨兵节点的抽象组合若干redis-sentinel进程
Redis哨兵(Sentinel)Redis提供的高可用方案哨兵节点集合和Redis主从节点
应用方泛指一个多多个客户端一个或多个连接Redis的进程

Redis 的主从复制模式可以将主节点的数据改变同步给从节点,这样从节点就可以起到两个作用:

  1. 作为主节点的一个备份,一旦主节点出了故障不可达的情况,从节点可以作为后备,并且保证数据尽量不丢失(主从复制表现为最终一致性)。
  2. 从节点可以分担主节点上的读压力,让主节点只承担写请求的处理,将所有的读请求负载均衡到各个从节点上。

但是主从复制模式并不是万能的,它同样遗留下以下几个问题:

  1. 主节点发生故障时,进行主备切换的过程是复杂的,需要完全的人工参与,导致故障恢复时间无法保障。
  2. 主节点可以将读压力分散出去,但写压力/存储压力是无法被分担的,还是受到单机的限制。

其中第一个问题是高可用问题,即 Redis 哨兵主要解决的问题。第二个问题是属于存储分布式的问题,留给 Redis 集群去解决,博客集中讨论第一个问题。


哨兵

当主节点出现故障时,Redis Sentinel能自动完成故障发现和故障转移,并通知应用方,从而实现真正的高可用。

Redis Sentinel是一个分布式架构,其中包含若干个 Sentinel 节点和 Redis 数据节点,每个Sentinel节点会对数据节点和其余 Sentinel节点进行监控,当它发现节点不可达时,会对节点做下线表示。

如果下线的是主节点,它还会和其他的 Sentinel 节点进行协商,当大多数 Sentinel 节点对主节点不可达这个结论达成共识之后,它们会在内部选举出一个领导节点来完成自动故障转移的工作,同时将这个变化实时通知给 Redis 应用方。整个过程是完全自动的,不需要人工介入。

整体的架构如图所示:

在这里插入图片描述

Redis Sentinel相比于主从复制模式多了若干Sentinel节点,用于实现监控数据节点。哨兵节点会定期监控所有节点(包含数据节点和其他哨兵节点)。

此处有多个哨兵节点,是因为如果只使用一个哨兵进行监控的话,如果哨兵本身就崩溃了,那么整个监控服务都崩溃了。另外的,在网络条件较差的情况下,哨兵很可能会误判主节点的存活情况。

针对主节点故障的情况,故障转移流程大致如下:

  1. 主节点故障,从节点同步连接中断,主从复制停止。
  2. 哨兵节点通过定期监控发现主节点出现故障。

哨兵节点与其他哨兵节点进行协商,达成多数认同主节点故障的共识。这步主要是防止出故障的不是主节点,而是发现故障的哨兵节点,该情况经常发生于哨兵节点的网络被孤立的场景下。

  1. 哨兵节点之间使用 Raft 算法选举出一个领导角色,由该节点负责后续的故障转移工作。
  2. 哨兵领导者开始执行故障转移
    • 从节点中选择一个作为新主节点,执行slave no one
    • 让其他从节点同步新主节,执行slaveof
    • 通知应用层转移到新主节点

Docker 搭建哨兵分布式

为了演示一个完整的Redis分布式架构,总共要创建三个数据节点,三个哨兵节点。由于大部分人都只有一台主机,所以此时的最佳解决方案是使用docker,接下来使用docker在一台主机上模拟一个分布式系统。

  • 拉取redis:5.0.9版本的镜像:
docker pull redis:5.0.9

当前目录结构如下:

在这里插入图片描述

redis-data用于存放数据节点,redis-sentinel用于存放哨兵节点。每个目录下都有docker-compose.yml,用于进行容器编排。

  • 编排 redis-data/docker-compose.yml
services:master:image: "redis:5.0.9"container_name: redis-masterrestart: alwayscommand: redis-server --appendonly yesports:- 6379:6379slave1:image: "redis:5.0.9"container_name: redis-slave1restart: alwayscommand: redis-server --appendonly yes --slaveof redis-master 6379ports:- 6380:6379slave2:image: "redis:5.0.9"container_name: redis-slave2restart: alwayscommand: redis-server --appendonly yes --slaveof redis-master 6379ports:- 6381:6379

该代码完成了三个数据节点的创建,通过命令完成主从关系的配置。执行之前,记得把主机上的redis停止,把637963806381三个端口空出来给docker启动的redis

在目录redis-data中执行:

docker compose up -d

在这里插入图片描述

这样就创建好了三个redis服务端,可以通过redis-cli -p 6379redis-cli -p 6380redis-cli -p 6381来验证是否启动成功。

  • 编排redis-sentinel/docker-compose.yml
services:sentinel1:image: 'redis:5.0.9'container_name: redis-sentinel-1restart: alwayscommand: redis-sentinel /root/redis/sentinel/redis-sentinel/sentinel1.confvolumes:- ./sentinel1.conf:/root/redis/sentinel/redis-sentinel/sentinel1.confports:- 26379:26379sentinel2:image: 'redis:5.0.9'container_name: redis-sentinel-2restart: alwayscommand: redis-sentinel /root/redis/sentinel/redis-sentinel/sentinel2.confvolumes:- ./sentinel2.conf:/root/redis/sentinel/redis-sentinel/sentinel2.confports:- 26380:26379sentinel3:image: 'redis:5.0.9'container_name: redis-sentinel-3restart: alwayscommand: redis-sentinel /root/redis/sentinel/redis-sentinel/sentinel3.confvolumes:- ./sentinel3.conf:/root/redis/sentinel/redis-sentinel/sentinel3.confports:- 26381:26379networks:default:external:name: redis-data_default

此处创建了三个redis-sentinel哨兵,并且规定它们的配置文件分别为./sentinel1.conf./sentinel2.conf./sentinel3.conf

但是docker存储卷要用绝对路径,所以你要根据自己的主机情况,填入绝对路径。

配置文件内容如下:

bind 0.0.0.0
port 26379
sentinel monitor redis-master redis-master 6379 2
sentinel down-after-milliseconds redis-master 1000

此处要简单解释一下配置文件:

sentinel monitor 主节点名 主节点ip 主节点端⼝ 法定票数
  • 主节点名

这个是哨兵内部自己起的名字

  • 主节点 ip

部署 redis-master的设备ip,此处由于是使用 docker,可以直接写 docker的容器名,会被自动 DNS 成对应的容器ip主节点端口。

  • 法定票数

哨兵需要判定主节点是否挂了,但是有的时候可能因为特殊情况,比如主节点仍然工作正常,但是哨兵节点自己网络出问题了,无法访问到主节点了。此时就可能会使该哨兵节点认为主节点下线,出现误判。使用投票的方式来确定主节点是否真的挂了是更稳妥的做法,需要多个哨兵都认为主节点挂了,票数 >=法定票数 之后,才会真的认为主节点是挂了。

  • sentinel down-after-milliseconds

该参数用于设置心跳包的超时时间,主节点和哨兵之间通过心跳包来进行沟通,如果心跳包在指定的时间内还没回来,就视为是节点出现故障。

既然多个配置文件内容相同,为啥要创建多份配置文件?redis-sentinel在运行中可能会对配置进行重写,修改文件内容,如果用一份文件,就可能出现修改混乱的情况。

最后执行命令,启动容器:

docker compose up -d

启动后,打开刚刚写的配置文件:

bind 0.0.0.0
port 26379
sentinel myid 15d2602413f32eb3ed797d804a728a59d65e43f1
sentinel deny-scripts-reconfig yes
# Generated by CONFIG REWRITE
dir "/data"
sentinel monitor redis-master 172.18.0.2 6379 2
sentinel down-after-milliseconds redis-master 1000
sentinel config-epoch redis-master 0
sentinel leader-epoch redis-master 0
sentinel known-replica redis-master 172.18.0.4 6379
sentinel known-replica redis-master 172.18.0.3 6379
sentinel known-sentinel redis-master 172.18.0.7 26379 475769f5605edb0016ad007ee06351e058589d4a
sentinel known-sentinel redis-master 172.18.0.5 26379 6ddca4a48f3ec926f8d8408794b261803aa6a5ad
sentinel current-epoch 0

可以看到,除了最开始写入的内容,哨兵启动后又增加了很多新内容。


选举

现在通过docker关掉master的容器,来模拟主节点崩溃:

docker stop redis-master

此时哨兵节点就已经在后台工作了,查看哨兵的日志:

docker compose logs

输出:

在这里插入图片描述

这是第二个哨兵的日志

  • sdown master:这代表哨兵节点发现了master节点掉线,sdown表示主观认为,也就是说哨兵还不能保证master一定掉线
  • odown master:经过与其它哨兵交流,多个哨兵都认为master节点掉线,odown表示客观认为,#quorum 3/2表示法定票数为2票,目前有三个哨兵都投票认为master掉线
  • switch-master:切换主节点,此时已经有新的节点变成主节点了

进入6380端口的数据节点,输入info replication

在这里插入图片描述

可以看到role:master6380成为了新的主节点,当然也有可能是6381

尝试重启redis-master

在这里插入图片描述

这个redis-master重启后,就变成了从节点,不再是主节点了。


流程

看完选举的现象后,接下来讲解一下选举的具体流程。

  • 主观下线 sdown

当主节点宕机,此时主节点和哨兵之间的心跳包就没有了响应,站在三个哨兵的角度来看,主节点出现严重故障,因此三个哨兵均会把主节点判定为主观下线

  • 客观下线 odown

此时,哨兵均会对主节点故障这件事情进行投票,当故障得票数 >= 法定票数之后,这意味着主节点故障这个事情被做实了,触发客观下线

  • 选取哨兵leader

接下来需要哨兵把剩余的slave 中挑选出一个新的master ,这个工作不需要所有的哨兵都参与,只需要选出个代表 (称为 leader),由leader负责进行 slave 升级到 master 的提拔过程,这个选举的过程涉及到 Raft 算法:

  1. 每个哨兵节点都给其他所有哨兵节点发起一个拉票请求"
  2. 收到拉票请求的节点,会回复一个投票响应当哨兵节点收到多个拉票请求,只对第一个节点投票,后续节点都不投票
  3. 一轮投票完成之后,发现得票超过半数的节点,自动成为 leader 如果出现平票的情况,就重新再投一次即可。

因此建议哨兵节点设置成奇数,如果是偶数个,则增大了平票的概率,带来不必要的开销。

最终leader 节点负责挑选一个 slave 成为新的 master 当其他的 sentenal发现新的 master 出现了,就说明选举结束了。

简而言之,Raft 算法的核心就是"先下手为强"谁率先发出了拉票请求,谁就有更大的概率成为 leader,这里的决定因素成了"网络延时"。

在这里插入图片描述

在日志中,vote-for-leader就是在投票选举leader哨兵。

  • leader哨兵节点选出一个 slave 成为新的 master

挑选规则:

  1. 比较优先级,优先级高(数值小的)的优先上位,优先级是配置文件中的配置项中的 slave-priority 或者replica-priority)
  2. 如果优先级相同,比较 replicationoffset 谁复制的数据多,高的优先上位
  3. 如果replicationoffset也相同,比较 run id ,小的优先上位,

当某个数据节点被选为master后:

  1. leader哨兵指定该节点执行slave no one,成为master
  2. leader哨兵指定剩余节点执行slave of,成为该节点的从节点

总结一下:

  • 主观下线 sdown:单个哨兵节点认为主节点掉线
  • 客观下线 odown:投票后客观认为主节点掉线
  • 选取哨兵leader:依据网络情况,选出一个哨兵成为leader,由leader完成选举master
  • 选举master:由leader依据优先级,数据同步进度,run id来选出一个节点成为master
  • 重构主从关系:由leader哨兵,指定数据节点执行指令,重构主从关系

注意事项:

  • 哨兵节点不能只有一个,否则哨兵节点挂了也会影响系统可用性
  • 哨兵节点最好是奇数个,方便选举 leader,得票更容易超过半数
  • 哨兵节点不负责存储数据,仍然是 redis 主从节点负责存储.
  • 哨兵+主从复制解决的问题是"提高可用性",不能解决"数据极端情况下写丢失"的问题,哨兵+主从复制不能提高数据的存储容量

相关文章:

Redis:分布式 - 哨兵

Redis:分布式 - 哨兵 概念哨兵 Docker 搭建哨兵分布式选举流程 概念 Redis 的主从复制模式下,一旦主节点由于故障不能提供服务,需要人工进行主从切换,同时大量的客户端需要被通知切换到新的主节点上,对于上了一定规模…...

开源城市运动预约的工具类小程序源码

运动场馆预约小程序是一款主要针对城市运动预约的工具类程序, 产品主要服务人群为20-45岁运动爱好者, 程序前后端完整代码,包括场馆动态,运动常识,羽毛球场地预约,足球场地预约,篮球场地预约&a…...

SldWorks问题 2. 矩阵相关接口使用上的失误

问题 在计算三维点在图纸(DrawingDoc)中的位置时,就是算不对,明明就4、5行代码,怎么看都是很“哇塞”的,毫无问题的。 但结果就是不对。 那就调试一下吧,调试后发现生成的矩阵很不对劲&#…...

2024十月超全大模型常见面试题(附答案)

大模型相关的面试问题通常涉及模型的原理、应用、优化以及面试者对于该领域的理解和经验。以下是一些常见的大模型面试问题以及建议的回答方式: 请简述什么是大模型,以及它与传统模型的主要区别是什么? 回答:大模型通常指的是参…...

Java 的数据结构整理(整合版)

Java 的数据结构整理(整合版) 一、数据输入输出 https://www.runoob.com/java/java-scanner-class.html 这部分是为了预防 leetcode 刷习惯了,忘记怎么处理输入输出的问题 数据输入 Java的数据输入和 C 相比非常繁琐,因此大多…...

如何让信息学奥赛学习“边玩边学”?——趣味编程让枯燥学习变得有趣

信息学奥赛(NOI)作为一项高水平的编程竞赛,内容涉及到大量的算法、数据结构和复杂的逻辑思维,对学生的要求非常高。然而,面对枯燥的知识点和高难度的题目,很多学生在备赛过程中容易感到乏味甚至放弃。那么&…...

【艾思科蓝】C++游戏开发探秘:打造高性能游戏世界的钥匙

【IEEE出版 | 院士、Fellow报告】第八届电气、机械与计算机工程国际学术会议(ICEMCE 2024)_艾思科蓝_学术一站式服务平台 更多学术会议请看:学术会议-学术交流征稿-学术会议在线-艾思科蓝 引言 在当今的游戏开发领域,C以其高效、…...

企业如何做好数据安全防泄密?10个你不知道的防泄密措施

随着数字化转型的加速推进,企业在处理和存储大量数据时,数据泄密风险也显著增加。从客户资料到商业机密,敏感数据一旦泄露,可能对企业造成不可估量的损失。为了更好地应对这一挑战,企业需要采取全面的防泄密策略。以下…...

MySQL基本操作(1)

初始数据库 数据库的基本概念 数据库是一个按照数据结构来组织、存储和管理数据的仓库,换句话说,就是存储数据的仓库。 为何使用数据库?使用数据库不仅仅为了使数据持久化,还能使得数据能够进行有效的管理,以…...

Python 如何使用 Redis 作为缓存

Python 如何使用 Redis 作为缓存 一、引言 在现代 Web 应用程序和数据密集型服务中,性能 和 响应速度 是至关重要的因素。而当应用需要频繁访问相同的数据时,直接从数据库获取数据会耗费大量的时间和资源。因此,缓存系统成为了提升性能的重…...

Python知识点:基于Python工具,如何使用Mediapipe进行人体姿态估计

开篇,先说一个好消息,截止到2025年1月1日前,翻到文末找到我,赠送定制版的开题报告和任务书,先到先得!过期不候! 基于Python的Mediapipe人体姿态估计技术详解 在计算机视觉领域,人体…...

数据结构进阶:二叉搜索树_C++

目录 前言: 一、二叉搜索树 1.1二叉搜索树概念 2.2 二叉搜索树操作 1. 二叉搜索树的插入 1.1、插入过程 1.2、代码实现 2、二叉树的删除 2.1、结点删除情况 2.2、替换删除法 1、替换思路 2、代码实现: 3、二叉搜索树的查找 3.1、查找规则 …...

uni-app之旅-day04-商品列表

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 前言6. 商品列表6.0 创建 goodslist 分支6.1 定义请求参数对象6.2 获取商品列表数据6.3 渲染商品列表结构6.4 把商品 item 项封装为自定义组件在 goods_detail 组件…...

单元测试的定义

概念 单元测试是对软件中的最小可测试单元进行检查和验证的过程。在面向对象编程中,最小可测试单元通常是一个方法或者一个类。它的目的是隔离各个部分的代码,确保每个单元都能按预期工作,从而提高软件的质量和可维护性。重要性 发现早期错误…...

C语言从头学66—学习头文件 <stdio.h>(二)

关于可变参数,我们曾经在《C语言从头学27》中接触过,下面学习能够接收可变参数作为 参数的几个函数。 一、printf函数的能够接收可变参数的变体函数: 1、函数vprintf() 功能:按照给定格式,将可变参数中的内容输…...

python静默活体检测接口集成-人脸识别API-人脸认证

静默活体检测是一种不需要用户主动配合(如眨眼、点头等)的活体检测技术,通常通过摄像头采集用户的人脸图像,结合计算机视觉与AI算法来判断用户是否为真人。这项技术被广泛应用于身份验证、金融交易安全、智能门禁等领域。 确定接口…...

Ubuntu安装nvidia显卡驱动

一、安装依赖 1、更新 sudo apt update sudo apt upgrade -y 2、基础工具 sudo apt install -y build-essential cmake 图形界面相关 sudo apt install -y lightdm 注:在弹出对话框选择"lightdm" 下载nvidia驱动: 进入如下网址:http…...

vulnhub-Web Developer 1靶机

vulnhub:Web Developer: 1 ~ VulnHub 导入靶机,放在kali同网段,扫描 靶机在192.168.114.129,扫描端口 有网站服务,访问 没什么东西,扫目录 真不少,访问一下,也只是一些普通的Wordpr…...

安全帽头盔检测数据集 3类 12000张 安全帽数据集 voc yolo

安全帽头盔检测数据集 3类 12000张 安全帽数据集 voc yolo 安全帽头盔检测数据集介绍 数据集名称 安全帽头盔检测数据集 (Safety Helmet and Person Detection Dataset) 数据集概述 该数据集专为训练和评估基于YOLO系列目标检测模型(包括YOLOv5、YOLOv6、YOLOv7…...

保姆级教程 | Adobe Illustrator调整颜色透明度

背景 由于课题需要,现需要在Adobe Illustrator里修改部分色块的颜色及透明度 步骤 1. 打开Adobe Illustrator软件,打开或创建一个AI文件: 2. 绘制一个色块: 3. 单击需要调整透明度的对象将其选中 4. 调整颜色的透明度&#xf…...

深入解读DeepSort目标跟踪算法:从状态预测到运动模型

在目标跟踪领域中,DeepSort(Deep Simple Online and Realtime Tracking)是一种广泛应用且高效的跟踪算法,它结合了深度学习与经典目标跟踪方法,为视觉跟踪任务提供了强大的解决方案。本文将深入探讨DeepSort中的关键概…...

24-10-2-读书笔记(二十二)-《契诃夫文集》(一)上([俄] 契诃夫 [译] 汝龙)啊!真想生活。

文章目录 《契诃夫文集》(一)上([俄] 契诃夫 [译] 汝龙 )早期生活——塔甘罗格(人物家庭简介)学生时期——莫斯科(写作与学习)流浪时期——哈萨林(游历与流浪&#xff09…...

【2024】前端学习笔记14-JavaScript常用数据类型-变量常量

学习笔记 1.JavaScript常用数据类型1.1.Number(数字)1.2.String(字符串)1.3.Boolean(布尔值)1.4.Null(空值)1.5.Undefined(未定义)1.6.Object(对象…...

Leecode热题100-48.旋转图像

给定一个 n n 的二维矩阵 matrix 表示一个图像。请你将图像顺时针旋转 90 度。 你必须在 原地 旋转图像,这意味着你需要直接修改输入的二维矩阵。请不要 使用另一个矩阵来旋转图像。 示例 1: 输入:matrix [[1,2,3],[4,5,6],[7,8,9]] 输出…...

重学SpringBoot3-集成Redis(二)之注解驱动

更多SpringBoot3内容请关注我的专栏:《SpringBoot3》 期待您的点赞👍收藏⭐评论✍ 重学SpringBoot3-集成Redis(二)之注解驱动 1. 为什么选择 Redis 作为缓存?2. 如何在 Spring Boot 中启用 Redis 缓存?2.1 …...

【React】入门Day04 —— 项目搭建及登录与表单校验、token 管理、路由鉴权实现

项目搭建 创建项目 # 使用npx创建项目 npx create-react-app my-react-app # 进入项目目录 cd my-react-app # 创建项目目录结构 mkdir -p src/{apis,assets,components,pages,store,utils} touch src/{App.js,index.css,index.js} 使用npx create-react-app创建项目&#xff0…...

CMake 属性之目录属性

【写在前面】 CMake 的目录属性是指在特定目录(及其子目录)范围内有效的设置。 这些属性不同于全局变量或目标(Target)属性,它们提供了一种机制,允许开发者为项目中的不同部分定义不同的构建行为。 通过目录…...

ChatGPT:引领人工智能新潮流!

一、ChatGPT 是什么? 1. ChatGPT 的强大功能和广泛应用。 ChatGPT 作为一款先进的 AI 语言模型,拥有众多强大功能。它可以进行文本生成、文本分类、情感分析、机器翻译等多种自然语言处理任务。同时,ChatGPT 还能进行对话式交互,…...

【银河麒麟高级服务器操作系统】安全配置基线相关分析全过程及解决方案

了解更多银河麒麟操作系统全新产品,请点击访问 麒麟软件产品专区:https://product.kylinos.cn 开发者专区:https://developer.kylinos.cn 文档中心:https://documentkylinos.cn 服务器环境以及配置 【机型】物理机或虚机 【…...

用Python实现图片转ASCII艺术:图像处理与字符艺术的完美结合

解锁Python编程的无限可能:《奇妙的Python》带你漫游代码世界 ASCII艺术是一种通过字符来表现图像的艺术形式,最早用于早期计算机显示器,它仅支持字符显示。如今,尽管图像分辨率和显示技术得到了极大的提升,ASCII艺术作为一种复古而别具一格的图像表现形式,仍然受到许多…...