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

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

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

相关文章

浏览器动态移动的小球源码分享

浏览器动态移动的小球源码分享 <script>(function(a){var width100,height100,borderRadius100,circlefunction(){};circle.prototype{color:function(){let colour "#"Math.floor(Math.random()*255).toString(16)Math.floor(Math.random()*255).toString…

Linux块设备驱动实验

直接参考【正点原子】I.MX6U嵌入式Linux驱动开发指南V1.81 本文仅作为个人笔记使用&#xff0c;方便进一步记录自己的实践总结。 前面我们都是在学习字符设备驱动&#xff0c;本章我们来学习一下块设备驱动框架&#xff0c;块设备驱动是Linux 三大驱动类型之一。块设备驱动要远…

Fiddler配合wireshark解密ssl

环境&#xff1a; win11&#xff08;wireshark&#xff09;--虚拟机win7&#xff08;Fiddler&#xff09;---虚拟机win7&#xff08;HTTPS站点&#xff09; 软件安装问题&#xff1a; 需要.net环境&#xff0c;NDP461-KB3102436-x86-x64-AllOS-ENU.exe。 安装fiddler后安装下…

vite项目打包md5报‘default‘ is not exported错误的解决方法

报错如下&#xff1a; 某一个包中用es方式引入md5模块&#xff0c;导致打包报错&#xff0c;经过一番探究测试&#xff0c;发现我的项目中用了“vite-plugin-require-transform”这个插件&#xff0c;是这个插件在做转换的时候报错了&#xff0c;如果你也是这个原因可按我的方式…

代码随想录day24:贪心part2

121. 买卖股票的最佳时机 class Solution {public int maxProfit(int[] prices) {int ans 0;int minPrice prices[0];for(int p : prices){ans Math.max(ans, p - minPrice);minPrice Math.min(p, minPrice);}return ans;} } 运用前缀和思想&#xff0c; 从左到右枚举卖…

Spring Boot教学资源库:构建微服务的基石

2 相关技术简介 2.1Java技术 Java是一种非常常用的编程语言&#xff0c;在全球编程语言排行版上总是前三。在方兴未艾的计算机技术发展历程中&#xff0c;Java的身影无处不在&#xff0c;并且拥有旺盛的生命力。Java的跨平台能力十分强大&#xff0c;只需一次编译&#xff0c;任…

dart-sass和node-sass的区别,使用dart-sass后可能会出现的问题

前言&#xff1a; 2020 年 10 月 27 日&#xff0c;Sass 官方团队正式宣布 Libsass 将弃用&#xff0c;以及基于它的 Node Sass 和 SassC&#xff0c;并且建议用户使用 Dart Sass。如果在 vue 脚手架搭建的项目中需要使用 sass&#xff0c;建议初始化时勾选 sass 配置&#xff…

前端优化之路:git commit 校验拦截

但是想要做到高效落地执行&#xff0c;就需要做些别的功课&#xff0c;先展示下成果图 需要了解git hooks&#xff0c;它是git的钩子&#xff0c;就像vue拥有自己的钩子一样。 官方文档&#xff1a;https://git-scm.com/docs/githooks 项目安装 husky&#xff0c;建议稳定版本…

patch函数前两个参数位

如我们多了解的&#xff0c;patch函数前两个参数位为 oldVnode 和 Vnode &#xff0c;分别代表旧节点和新节点&#xff0c;主要做了四个判断&#xff1a; patchVnode主要做了两个判断&#xff1a;

java中Math类和Random类的api

目录 Math 类 1&#xff09;abs(x) 2&#xff09;ceil(x) 3&#xff09;floor(x) 4&#xff09;round(x) 5&#xff09;max(x, y) 6&#xff09;min(x, y) 7&#xff09;sqrt(x) 8&#xff09;pow(x, y) 9&#xff09;random() 10&#xff09;sin(x), cos(x), tan(x) 11&#x…

购物网站毕业设计-电子电器商城管理系统SpringBootSSM框架开发

目录 1. 系统概述 1.1背景介绍 1.2 课题意义 1.3课题目标 2. 主要功能模块 2.1 前端用户模块 2.2 后端管理模块 2.3 功能图展示 3. 技术选型 3.1 VUE介绍 3.2 JAVA介绍 3.3 MySQL介绍 4. 系统设计 4‌.1数据库设计 5 详细设计 5.1 界面展示 设计一个电子电…

通过Keil5编译软件获取函数最深堆栈

文章目录 1.问题提出2.问题分析3.环境搭建4.解决方案5.经验总结6.疑问 1.问题提出 在编写新软件时&#xff0c;由于某功能需要使用RAM约24KB&#xff0c;而新模块的总RAM是96KB&#xff0c;该某功能一旦开启则需要占用四分之一的RAM空间。为了保证在开启某功能后&#xff0c;新…

WPF中的Window类

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

高性能缓存方案 —— Caffeine

一、简介 Caffeine是一个高性能的Java缓存库&#xff0c;它提供了本地缓存的功能。 Caffeine和Redis都是内存级别的缓存&#xff0c;为什么要使用在这两缓存作为二级缓存&#xff0c;它们两有什么区别呢? 虽然它们都是内存级别的缓存&#xff0c;但是Redis是需要单独部署的&…

【开源风云】从若依系列脚手架汲取编程之道(五)

&#x1f4d5;开源风云系列 &#x1f34a;本系列将从开源名将若依出发&#xff0c;探究优质开源项目脚手架汲取编程之道。 &#x1f349;从不分离版本开写到前后端分离版&#xff0c;再到微服务版本&#xff0c;乃至其中好玩的一系列增强Plus操作。 &#x1f348;希望你具备如下…

鸿蒙OS投票机制

(基于openharmony5.0) 投票机制 param get | grep ohos.boot.time 图 投票机制参数图 只有当所有的投票完成&#xff0c;开机动画才会退出&#xff0c;整理需要投票的系统应用&#xff08;三方应用不参与投票&#xff09;如下图所示&#xff1a; 以进程foundation为例&…

Python案例--copy复制

在Python编程中&#xff0c;数据的复制是一个常见且重要的操作&#xff0c;它涉及到赋值、浅拷贝和深拷贝三种不同的概念。正确理解这三种操作对于编写高效且正确的程序至关重要。本文将通过一个简单的Python示例&#xff0c;探讨这三种数据复制方式的区别及其应用场景&#xf…

计算机视觉之OpenCV vs YOLO

好多开发者希望搞明白OpenCV 和YOLO区别&#xff0c;实际上&#xff0c;二者在计算机视觉领域都有广泛应用&#xff0c;但它们有很大的不同。 一、OpenCV 概述 OpenCV&#xff08;Open Source Computer Vision Library&#xff09;是一个开源的计算机视觉和机器学习软件库。它…

软考攻略/超详细/系统集成项目管理工程师/基础知识分享12

5.1 软件工程定义&#xff08;了解&#xff09; 软件工程是指应用计算机科学、数学及管理科学等原理&#xff0c;其目的是提高软件生产率、提高软件质量、降低软件成本。 5.2 软件需求&#xff08;掌握&#xff09; 5.2.1 需求的层次&#xff08;掌握&#xff09; 软件需求是指…

打造直播美颜平台的关键技术:视频美颜SDK的深度解析

本篇文章&#xff0c;小编将深入解析视频美颜SDK的关键技术&#xff0c;探讨其在打造直播美颜平台中的作用。 一、视频美颜SDK的定义与功能 视频美颜SDK是一套专门为实时视频处理而设计的软件开发工具包。其主要功能包括人脸检测、肤色美化、瑕疵修复、虚化背景、实时滤镜等。…