Redis:分布式 - 哨兵

news2024/10/10 15:28:12

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-master
    restart: always
    command: redis-server --appendonly yes
    ports:
      - 6379:6379
  slave1:
    image: "redis:5.0.9"
    container_name: redis-slave1
    restart: always
    command: redis-server --appendonly yes --slaveof redis-master 6379
    ports:
      - 6380:6379
  slave2:
    image: "redis:5.0.9"
    container_name: redis-slave2
    restart: always
    command: redis-server --appendonly yes --slaveof redis-master 6379
    ports:
      - 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-1
    restart: always
    command: redis-sentinel /root/redis/sentinel/redis-sentinel/sentinel1.conf
    volumes:
      - ./sentinel1.conf:/root/redis/sentinel/redis-sentinel/sentinel1.conf
    ports:
      - 26379:26379
  sentinel2:
    image: 'redis:5.0.9'
    container_name: redis-sentinel-2
    restart: always
    command: redis-sentinel /root/redis/sentinel/redis-sentinel/sentinel2.conf
    volumes:
      - ./sentinel2.conf:/root/redis/sentinel/redis-sentinel/sentinel2.conf
    ports:
      - 26380:26379
  sentinel3:
    image: 'redis:5.0.9'
    container_name: redis-sentinel-3
    restart: always
    command: redis-sentinel /root/redis/sentinel/redis-sentinel/sentinel3.conf
    volumes:
      - ./sentinel3.conf:/root/redis/sentinel/redis-sentinel/sentinel3.conf
    ports:
      - 26381:26379

networks:
  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 主从节点负责存储.
  • 哨兵+主从复制解决的问题是"提高可用性",不能解决"数据极端情况下写丢失"的问题,哨兵+主从复制不能提高数据的存储容量

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

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

相关文章

美发店管理升级:SpringBoot技术实现

3系统分析 3.1可行性分析 通过对本美发门店管理系统实行的目的初步调查和分析,提出可行性方案并对其一一进行论证。我们在这里主要从技术可行性、经济可行性、操作可行性等方面进行分析。 3.1.1技术可行性 本美发门店管理系统采用SSM框架,JAVA作为开发语…

产业园区数字化转型:破解传统园区发展瓶颈

在当今数字化浪潮汹涌澎湃的时代,传统产业园区面临着诸多发展瓶颈,而产业园区数字化转型成为了突破这些困境的关键路径。 传统产业园区往往存在着管理效率低下、资源配置不合理、企业间协同困难以及创新能力不足等问题。这些问题就像一道道枷锁&#xf…

胃阴亏则百病生!阴虚火旺、胃病多发、灼痛?秋冬滋补季,用“仙草”养养胃~

中国有句俗话“十人九胃”,现代社会作息混乱、饮食无度,胃病的患病率也变得越来越高。 经常熬夜,饮食不规律,暴饮暴食,肠胃不适,面色差~ 喜食辛辣,总吃烧烤,烘烤、辛辣热性的食物&…

线下旅行社增长:单品牌半年新开500家门店,净利润增幅超307%

实体门店集体下行,旅行社缘何能越开越多 前言 线上流量井喷背景下,旅游业却“反其道而行”,重燃线下旅行社战火。 文化和旅游部市场管理司今年9月发布的《2024年第二季度全国旅行社统计调查报告》显示,截至2024年6月30日&#…

WPF中的常用控件

控件分类 在第一篇文章.Net Core和WPF介绍中的WPF的功能和特性部分根据功能性介绍了WPF的控件 名称。 在接下来的文章中,将会详细的介绍各个控件的概念及使用。 主要包括: 内容控件:Label、Button、CheckBox、ToggleButton、RadioButton、…

Large AI Model Empowered Multimodal Semantic Communications——基于大模型的多模态语义通信框架

1. 背景 本文讨论了大规模AI模型在多模态语义通信(SC)系统中的应用,处理不同类型的数据(文本、音频、图像、视频)以实现低延迟、高质量的语义层次通信。提出了一个基于大模型的多模态SC(LAM-MSC&#xff09…

心理学基础

一,三观 三观包括世界观、人生观、价值观。 1,世界观 世界观‌是人们对整个世界的总的看法和根本观点。可以划分为两种根本对立的世界观类型,即唯心主义世界观和唯物主义世界观。 2,人生观 人生观是人们在实践中形成的对于人…

[C高手编程] C语言数据结构:排序算法与查找算法

💖💖⚡️⚡️专栏:C高手编程-面试宝典/技术手册/高手进阶⚡️⚡️💖💖 「C高手编程」专栏融合了作者十多年的C语言开发经验,汇集了从基础到进阶的关键知识点,是不可多得的知识宝典。如果你是即将…

开发一个exe应用工具,pdf转图片工具,pdf截成单个图片,然后全量修整没用的白边

pdf转图片工具 图片裁剪白边工具 window系统exe应用工具下载地址https://download.csdn.net/download/websmallrabbit/89864476如果有帮助到您还请动动手帮忙点赞,关注,评论转发,感谢啦!💕💕💕&…

记一次详细的实战渗透

声明:本文仅限于技术讨论与分享,严禁用于非法途径。若读者因此作出任何危害网络安全行为后果自负,与本号及原作者无关。 前言 一次授权的渗透测试,过程比较详细,充满了巧合,也算比较有意思直接记录一下&a…

SpringBoot访问web中的静态资源

SpringBoot访问web中的静态资源,有两个方式: 1、SpringBoot默认指定了一些固定的目录结构,静态资源放到这些目录中的某一个,系统运行后浏览器就可以访问到 ① 关键是SpringBoot默认指定的可以存放静态资源的目录有哪些&#xff…

这几个被淘汰的Python库,请不要再用!

随着每个 Python 版本的发布,都会添加新模块,并引入新的更好的做事方式,虽然我们都习惯了使用好的旧 Python 库和某些做事方式,但现在也时候升级并利用新的和改进的模块及其特性了。 这里插播一条粉丝福利,如果你正在…

图片美化SDK解决方案,赋能H5与小程序极致体验

无论是社交媒体分享、电商产品展示,还是个人日常生活的记录,一张经过精心美化的图片总能瞬间吸引眼球,传递出更加丰富和动人的信息。如何在不增加应用体积、不牺牲用户体验的前提下,为H5页面和小程序提供媲美原生APP的图片美化功能…

二、IOC容器

文章目录 1. IOC的底层原理1.1 什么是IOC1.2 IOC 底层原理1.3 画图讲解 IOC 底层原理 2. IOC接口(BeanFactory)3. IOC 操作 Bean 管理(概念)3.1 什么是Bean管理3.2 Bean管理操作的两种方式 4. IOC操作 Bean 管理(基于 …

go发送邮件:在Go语言中实现发邮件的教程?

go发送邮件的教程指南?怎么使用Go语言发送电子邮件? Go语言,作为一种简洁、高效且并发性强的编程语言,自然也提供了丰富的库来支持邮件发送功能。AokSend将详细介绍如何在Go语言中实现发送邮件的功能,帮助你快速掌握这…

Video Ocean,又一AI视频生成神器!

Video Ocean,又一AI视频生成神器! 引言 大家好,今天想和大家聊聊一个特别的工具——Video Ocean。在如今这个短视频盛行的时代,大家都知道,制作一个吸引眼球的视频可不是一件简单的事情。传统的视频编辑软件复杂又费…

Gin解说

Gin是一个用Go语言编写的高性能、开源的Web框架,它被设计为简单、快速和灵活。Gin非常适合用于构建RESTful API和微服务。以下是Gin框架的一些核心特点: 特点 1.高性能:Gin使用了高速的HTTP路由器,它基于Radix树实现&#xff0c…

AI直播元年:盘点2025年经典实用的十款AI直播工具,特别是第一款!

AI直播元年:盘点2025年经典实用的十款AI直播工具,特别是第一款! 随着人工智能(AI)技术的飞速发展,直播行业正经历着前所未有的变革。2025年,被誉为“AI直播元年”,这一年见证了众多…

2.4 Service服务层

今天,我将向大家介绍在Spring Boot应用程序中实现Service层的方法,并通过实战演示如何测试Service层。 首先,让我们回顾一下Service层在MVC架构中的作用。Service层位于Model和Controller之间,主要负责处理业务逻辑。它封装了应用…

多线程—— Thread 类及常见用法(详解)

前言 本篇文章会介绍 Java 中的 Thread 类常见的构造方法、常见属性及其常见的用法,会列举一些代码例子来更直观的感受每个方法是作用,文章还会介绍 Java 中线程的状态及他们之间的转换关系,那么下面就开始今天的分享吧~~ 一、常见构造方法 …