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

redis中的哨兵

redis中的哨兵

    • 一、哨兵机制的概念
    • 二、redis哨兵的部署
      • 2.1 docker的安装
      • 2.2 编排redis主从节点
      • 2.3 配置哨兵节点
    • 三、redis哨兵的选举机制
      • 3.1 redis-master宕机之后的情况
      • 3.2 重启redis-master后的情况
    • 四、redis哨兵机制的原理
      • 4.1主观下线
      • 4.2客观下线
      • 4.3选举leader节点
      • 4.4选出合适的从节点
      • 4.5哨兵机制小结

Redis 的主从复制模式下,⼀旦主节点由于故障不能提供服务,需要⼈⼯进⾏主从切换,同时⼤量的客⼾端需要被通知切换到新的主节点上,对于上了⼀定规模的应⽤来说,这种⽅案是⽆法接受的,于是 Redis 从 2.8 开始提供了 Redis Sentinel(哨兵)来解决这个问题

一、哨兵机制的概念

Redis Sentinel 相关名词解释 :

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

Redis Sentinel 是 Redis 的⾼可⽤实现⽅案,在实际的⽣产环境中,对提⾼整个系统的⾼可⽤是⾮常有帮助的,本节⾸先整体梳理主从复制模式下故障处理可能产⽣的问题,⽽后引出⾼可⽤的概念,最后重点分析 Redis Sentinel 的基本架构、优势,以及是如何实现⾼可⽤的

哨兵⾃动恢复主节点故障

提供多个sentinel哨兵进程监控现有的redis master和slave。这些进程之间会建立tcp长连接,通过这样的长连接,定期发送心跳包。然后就可发现监控的节点是否挂了。

  • 如果从节点挂了,那么哨兵节点不予理会,认为对服务没有什么影响。

  • 如果一个哨兵发现主节点挂了,那么其它哨兵也会进行判断主节点是否挂了,如果超过法定票数个哨兵都认为主节点挂了,那么此时就会在这些从节点中,挑选一个节点作为新的主节点,挑选出的新节点,哨兵会自动控制该节点执行slaveof no one让其成为主节点,并且控制其他从节点,修改slaveof到新的主节点上。

  • 最后哨兵会自动通知客户端程序,告知新的主节点是谁,让客户端后续在进行写操作时,能够在新的主节点上操作,当原来的主节点恢复,执⾏ slaveof {newMasterIp} {newMasterPort}让其成为⼀个从节点

在这里插入图片描述

补充:一般哨兵节点会弄奇数个。

二、redis哨兵的部署

2.1 docker的安装

部署多个节点在一台主机上是非常麻烦的,所以这里使用docker来进行演示。

在Linux上安装docker可看这篇博客

2.2 编排redis主从节点

上述操作必须保证⼯作⽬录在yml的同级⽬录中, 才能⼯作

1.配置文件

在配置redis主从节点之前,先创建一个redis-slave文件夹,然后进入该文件夹,写一下配置文件docker-compose.yml:

version: '3.7' #版本号
services:   #表示启动的服务器master:   #服务名image: 'redis:5.0.9' #容器镜像名称container_name: redis-master  #自定义名称(也可以理解为ip地址)restart: always   #表示总是自动重启command: redis-server --appendonly yes #启动redis时启动的选项ports:- 6379:6379  #端口映射  前面是宿主机端口号  后面是虚拟机的端口号slave1:    #服务名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

补充:端口映射

docker容器,可以理解为一个轻量的虚拟机,在这个容器里,端口号和外面的宿主机的端口号是两个体系。如果容器外面使用了5000端口,在容器内部也可以使用5000端口,有时候希望在容器外面能够访问到容器内部的端口号,所以就把容器内部的端口和容器外面的端口进行映射。

容器使用相同的端口号不会冲突吗?

每个容器内部的端口号是不会互相影响的,可以把每个容器理解为一个独立的主机

2.执行指令,启动该配置文件中的docker容器

sudo docker-compose up -d

如果启动后发现前⾯的配置有误, 需要重新操作, 使⽤ docker-compose down 即可停⽌并删除刚才创建好的容器.

sudo docker-compose down

3.查看一下是否成功启动:

sudo docker ps -a

在这里插入图片描述

netstat -anp | grep -E '6379|6380|6381'

在这里插入图片描述

4.查看运⾏⽇志

sudo docker-compose logs

现在客户端就可以连接redis服务器了。

redis-cli -p 6379
redis-cli -p 6380
redis-cli -p 6381

补充:

也可以把 redis-sentinel 放到和上⾯的 redis 的同⼀个 yml 中进⾏容器编排. 此处分成两组, 主要是为了两⽅⾯:

  • 观察⽇志⽅便

  • 确保 redis 主从节点启动之后才启动 redis-sentinel. 如果先启动 redis-sentinel 的话, 可能触发额外的选举过程, 混淆视听. (不是说先启动哨兵不⾏, ⽽是观察的结果可能存在⼀定随机性)

2.3 配置哨兵节点

1.回到上级目录,新创一个文件夹sentinel,然后进到该文件夹,创建docker-compose.yml文件,然后配置:

version: '3.7'
services:sentinel1:image: 'redis:5.0.9'container_name: redis-sentinel-1restart: alwayscommand: redis-sentinel /etc/redis/sentinel.confvolumes:- ./sentinel1.conf:/etc/redis/sentinel.confports:- 26379:26379sentinel2:image: 'redis:5.0.9'container_name: redis-sentinel-2restart: alwayscommand: redis-sentinel /etc/redis/sentinel.confvolumes:- ./sentinel2.conf:/etc/redis/sentinel.confports:- 26380:26379sentinel3:image: 'redis:5.0.9'container_name: redis-sentinel-3restart: alwayscommand: redis-sentinel /etc/redis/sentinel.confvolumes:- ./sentinel3.conf:/etc/redis/sentinel.confports:- 26381:26379
networks:default:external:name: redis-slave_default  #加入到的局域网名,后面解释

2.创建 sentinel1.conf sentinel2.conf sentinel3.conf . 三份⽂件的内容是完全相同的

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

理解 sentinel monitor:

sentinel monitor 主节点名 主节点ip 主节点端⼝ 法定票数
  • 主节点名:这个是哨兵内部⾃⼰起的名字
  • 主节点 ip:部署 redis-master 的设备 ip. 此处由于是使⽤ docker, 可以直接写 docker 的容器名, 会被⾃动 DNS 成对应的容器 ip
  • 主节点端⼝:主节点的端口号
  • 法定票数:哨兵需要判定主节点是否挂了. 但是有的时候可能因为特殊情况, ⽐如主节点仍然⼯作正常, 但是哨兵节点⾃⼰⽹络出问题了, ⽆法访问到主节点了. 此时就可能会使该哨兵节点认为主节点下线, 出现误判. 使⽤投票的⽅式来确定主节点是否真的挂了是更稳妥的做法. 需要多个哨兵都认为主节点挂了, 票数 >= 法定票数 之后, 才会真的认为主节点是挂了

理解 sentinel down-after-milliseconds

主节点和哨兵之间通过⼼跳包来进⾏沟通. 如果⼼跳包在指定的时间内还没回来, 就视为是节点出现故障

既然内容相同, 为啥要创建多份配置⽂件?

redis-sentinel 在运⾏中可能会对配置进⾏ rewrite, 修改⽂件内容. 如果⽤⼀份⽂件, 就可能出现修改混乱的情况

3.启动该配置文件中的docker容器

sudo docker-compose up -d

如果启动后发现前⾯的配置有误, 需要重新操作, 使⽤ docker-compose down 即可停⽌并删除刚才创建好的容器

4.查看运⾏⽇志

docker-compose logs

在这里插入图片描述

出现“WARNING: Sentinel was not able to save the new configuration on disk!!!: Is a directory”错误的原因通常是因为文件权限问题。‌ 在Docker中部署Redis Sentinel时,如果配置文件没有正确的读写权限,Sentinel就无法保存新的配置到磁盘上

修改配置文件的权限‌:确保配置文件有适当的读写权限。可以通过以下命令修改权限:

sudo chmod 777 ./sentinel1.conf ./sentinel2.conf ./sentinel3.conf

这会将配置文件的权限设置为可读、可写、可执行,确保Sentinel能够正常保存配置

出现Reading the configuration file, at line 3 redis-sentinel-2 | >>> ‘sentinel monitor redis-master redis-master 6379 2’
redis-sentinel-2 | Can’t resolve master instance hostname.错误时,表示无法正确解析到主节点的ip地址

在这里插入图片描述

主要原因docker启动容器的时候,会把容器分配在不同的虚拟局域网中,此时主从节点和哨兵节点不在同一个虚拟局域网中,所以也就解析不了主节点的ip地址了。

可通过如下指令查看当前docker容器有哪些虚拟局域网:

docker network ls

主从节点与哨兵节点不在同一个局域网中,此时需要修改用于启动哨兵节点的配置文件docker-compose.yml文件。将虚拟局域网部分改为

networks:default:external:name: redis-slave_default

然后执行docker-compose down 命令将对应的哨兵节点关闭移除掉,然后在调用docker-compose up -d创建启动哨兵节点:

#关闭移除哨兵节点
sudo docker-compose down
#创建启动哨兵节点
sudo docker-compose up -d

哨兵节点启动成功后的日志

在这里插入图片描述

也可以通过如下指令,查看单个哨兵的日志:

#查看docker容器中启动的容器,可以得到哨兵节点的名称,ID
sudo docker ps -a
#得到sentinel名称,ID以后
sudo docker logs 容器的名称(或ID)

在这里插入图片描述

5.观察 redis-sentinel 的配置 rewrite

再次打开哨兵的配置⽂件, 发现⽂件内容已经被⾃动修改了

#配置文件信息
bind 0.0.0.0
port 26379
sentinel myid ccdae87d81bf00f23ca6d4ab869571ef046be71f
sentinel deny-scripts-reconfig yes
# Generated by CONFIG REWRITE
dir "/data"
sentinel monitor redis-master 172.18.0.3 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.2 6379
sentinel known-sentinel redis-master 172.18.0.6 26379 3b77e18de5fb4ce0bc214f6aa2665b77429a80f2
sentinel known-sentinel redis-master 172.18.0.5 26379 0ccfa9143d636099702b86b36daee36275818d1b
sentinel current-epoch 0

三、redis哨兵的选举机制

3.1 redis-master宕机之后的情况

为了让主节点宕机,我们可以手动把它关掉:

sudo docker stop redis-master

观察哨兵的⽇志:

在这里插入图片描述

可以看到哨兵发现了主节点 sdown, 进⼀步的由于主节点宕机得票达到 3/2 , 达到法定得票, 于是 master 被判定为 odown

  • 主观下线 (Subjectively Down, sdown): 哨兵感知到主节点没⼼跳了. 判定为主观下线

  • 客观下线 (Objectively Down, odown): 多个哨兵达成⼀致意⻅, 才能认为 master 确实下线了

接下来, 哨兵们挑选出了⼀个新的 master. 在上图中, 是 172.18.0.2:6379 这个节点

在这里插入图片描述

此时, 对于 Redis 来说仍然是可以正常使⽤的

3.2 重启redis-master后的情况

⼿动把 redis-master 启动起来:

sudo docker start redis-master

观察哨兵⽇志,可以看到刚才新启动的redis-master 被当成了 slave

在这里插入图片描述

可以登录该客户端执行验证:

redis-cli -p 6379

然后执行写的命令:

set key 'hello'

在这里插入图片描述

此时的redis-master(从节点)已经没有了写的权限。

总结:

  • Redis 主节点如果宕机, 哨兵会主观的认为主节点下线了,当主观认为主节点下线的票数超过一半以后,哨兵节点就会客观认为主节点下线了。

  • 然后哨兵节点会进行投票选举出一个leader哨兵节点(票数需要大于等于二分之一),来让从节点变成主节点。

  • 当之前的 Redis 主节点重启之后, 这个主节点被加⼊到哨兵的监控中, 但是只会被作为从节点使⽤.

四、redis哨兵机制的原理

假定当前环境如上⽅介绍, 三个哨兵(sentinel1, sentinel2, sentinel3), ⼀个主节点(redis-master), 两个从节点(redis-slave1, redis-slave2),当主节点出现故障, 就会触发⼀系列过程

在这里插入图片描述

4.1主观下线

当 redis-master 宕机, 此时 redis-master 和三个哨兵之间的⼼跳包就没有了,此时,站在三个哨兵的⻆度来看,redis-master 出现严重故障,因此三个哨兵均会把 redis-master 判定为主观下线 (sdown)

4.2客观下线

此时, 哨兵 sentinel1, sentinel2, sentinel3 均会对主节点故障这件事情进⾏投票. 当认为主节点下线的票数 >= 配置的法定票数之后,此时意味着 redis-master 故障这个事情被做实了,此时触发客观下线 (odown)

配置的法定票数

sentinel monitor redis-master 172.22.0.4 6379 2

在我们写哨兵节点的三个配置文件的时候,此处所写的2就是法定票数

4.3选举leader节点

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

假定⼀共三个哨兵节点, S1, S2, S3,选举过程如下:

  1. 每个哨兵节点都给其他所有哨兵节点, 发起⼀个 “拉票请求”. (S1 -> S2, S1 -> S3, S2 -> S1, S2 -> S3, S3 -> S1, S3 -> S2)
  2. 收到拉票请求的节点, 会回复⼀个 “投票响应”. 响应的结果有两种可能, 投 or 不投,每个节点只有一次投票机会,投了就不能再投了
  3. ⼀轮投票完成之后, 发现得票超过法定票数的节点, ⾃动成为 leader。如果出现平票的情况 (S1 投 S2, S2 投 S3, S3 投 S1, 每⼈⼀票), 就重新再投⼀次即可,这也是为啥建议哨兵节点设置成奇数个的原因. 如果是偶数个, 则增⼤了平票的概率, 带来不必要的开销.
  4. leader 节点负责挑选⼀个 slave 成为新的 master. 当其他的 sentenal 发现新的 master 出现了, 就说明选举结束了

简⽽⾔之, Raft 算法的核⼼就是 “先下⼿为强”. 谁率先发出了拉票请求, 谁就有更⼤的概率成为 leader,这⾥的决定因素成了 “⽹络延时”. ⽹络延时本⾝就带有⼀定随机性,所以哪个节点成为leader是不确定的,当然这也是无关紧要的,成为leader的目的就是为了提拔一个从节点让其成为主节点。

4.4选出合适的从节点

从节点变成主节点的选举规则:

  1. ⽐较优先级. 优先级⾼(数值⼩的)的上位,优先级是配置⽂件中的配置项( slave-priority 或者 replica-priority )
  2. ⽐较 replication offset 谁复制的数据多,⾼的上位
  3. ⽐较 run id , 谁的 id ⼩, 谁上位

当某个 slave 节点被指定为 master 之后,

  1. leader 指定该节点执⾏ slave no one , 成为 master
  2. leader 指定剩余的 slave 节点, 都依附于这个新 master

4.5哨兵机制小结

上述过程, 都是 “⽆⼈值守” , Redis ⾃动完成的. 这样做就解决了主节点宕机之后需要⼈⼯⼲预的问题, 提⾼了系统的稳定性和可⽤性

⼀些注意事项:

  • 哨兵节点不能只有⼀个,否则哨兵节点挂了也会影响系统可⽤性

  • 哨兵节点最好是奇数个,⽅便选举 leader,得票更容易超过半数

  • 哨兵节点不负责存储数据,仍然是 redis 主从节点负责存储

  • 哨兵 + 主从复制解决的问题是 “提⾼可⽤性”, 不能解决 “数据极端情况下写丢失” 的问题

  • 哨兵 + 主从复制不能提⾼数据的存储容量,当我们需要存的数据接近或者超过机器的物理内存,这样的结构就难以胜任了,此时就需要引入集群结构了。


http://www.mrgr.cn/news/78587.html

相关文章:

  • 吉他初学者学习网站搭建系列(8)——如何练习音阶
  • TsingtaoAI具身智能高校实训方案通过华为昇腾技术认证
  • [Code]R2U-Net中的眼部血管分割
  • 【拥抱AI】Milvus 如何处理 TB 级别的大规模向量数据?
  • 外卖点餐系统小程序
  • MD5算法加密笔记
  • ISO26262-基于TC397的MPU内存保护
  • mysql_题库详解
  • pyspark实现基于协同过滤的电影推荐系统
  • C底层 函数栈帧
  • Vuex —— Day1
  • 信创改造 - Redis -》TongRDS 安装方式之单节点模式安装
  • 哈希表算法题
  • 开发一套ERP 第八弹 RUst 插入数据
  • 《datawhale2411组队学习 模型压缩技术7:NNI剪枝》
  • 【Canvas与雷达】简约绿色扫描雷达图标
  • 【数据集划分】训练集train/验证集val/测试集test是如何划分的?
  • HarmonyOS NEXT应用开发,关于useNormalizedOHMUrl选项的坑
  • 51c自动驾驶~合集38
  • 随机变量的线性最小均方估计(LMMSE)——多个观测变量
  • 使用C#开发VTK笔记(一)-VTK开发环境搭建
  • 【数据库系统概论】第6章 (一)函数依赖和码
  • 3.26线性回归对率回归
  • 大米中的虫子检测-检测储藏的大米中是否有虫子 支持YOLO,VOC,COCO格式标注,4070张图片的数据集
  • 2008年IMO几何预选题第3题
  • Gazebo插件相机传感器(可订阅/camera/image_raw话题)