Redis的分布式部署方案-哨兵

news2024/9/20 21:39:30

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主从复制的流程

哨兵机制,是通过独立的进程来体现的,和之前的redis-server是不同的进程

redis-sentinel不负责存储数据,只是对其他的redis-server进程起到监控的作用

手动恢复redis主从复制的流程

服务器,要求要有比较高的可用性,7*24运行;服务器长期运行,总会有一些”意外",具体啥时候出意外,咱们也不知道,同时也不能全靠人工来盯着服务器运行;我们可以写一个程序,用程序来盯着服务器的运行状态(监控程序,发现服务器的运行出现状态异常了;往往还需要搭配“报警程序”)

  1. 运维⼈员通过监控系统,发现 Redis 主节点故障宕机
  2. 运维⼈员从所有节点中,选择⼀个(此处选择了 slave 1)执⾏ slaveof no one,使其作为新的主 节点
  3. 运维⼈员让剩余从节点(此处为 slave 2)执⾏ slaveof {newMasterIp} {newMasterPort} 从新主节 点开始数据同步
  4. 更新应⽤⽅连接的主节点信息到 {newMasterIp} {newMasterPort}
  5. 如果原来的主节点恢复,执⾏ slaveof {newMasterIp} {newMasterPort} 让其成为⼀个从节点。 上述过程可以看到基本需要⼈⼯介⼊,⽆法被认为架构是⾼可⽤的。⽽这就是 Redis Sentinel 所要做 的。

如果操作过程出错了咋办,并且恢复的过程也得半个小时以上,这显然并不合适。

自动恢复redis主从复制的流程

监控:这些进程之间,会建立tcp长连接,通过这样的长连接,定期发送心跳包;借助上图的监控机制,就可以及时发现某个主机是否是挂了,如果是从节点挂了,其实没关系;如果是主节点挂了,哨兵就会发挥作用

Redis Sentinel 相⽐于主从复制模式是多了若⼲(建议保持奇数)Sentinel 节点⽤于实现监控数据节 点,哨兵节点会定期监控所有节点(包含数据节点和其他哨兵节点)。针对主节点故障的情况,故障转移流程⼤致如下:

  1. 主节点故障,从节点同步连接中断,主从复制停⽌
  2. 哨兵节点通过定期监控发现主节点出现故障。哨兵节点与其他哨兵节点进⾏协商,达成多数认同主 节点故障的共识。这步主要是防⽌该情况:出故障的不是主节点,⽽是发现故障的哨兵节点,该情况经常发⽣于哨兵节点的⽹络被孤⽴的场景下
  3. 哨兵节点之间使⽤ Raft 算法选举出⼀个领导⻆⾊,由该节点负责后续的故障转移⼯作
  4. 哨兵领导者开始执⾏故障转移:从节点中选择⼀个作为新主节点;让其他从节点同步新主节点;通知应⽤层(客户端)转移到新主节点。

redis哨兵核心功能:

  • 监控
  • 自动的故障转移
  • 通知

redis哨兵节点,有一个也是可以的,但是:

  1. 如果哨兵节点只有一个,它自身也是容易出现问题的,万一这个哨兵节点挂了,后续redis节点也挂了,就无法进行自动的恢复过程了
  2. 出现误判的概率也比较高,网络传输数据是容易出现抖动或者延迟或者丢包的,如果只有一个哨兵节点,出现上述问题之后,影响就比较大
  • 基本原则:在分布式系统中,应该避免使用“单点”
  • 哨兵节点,最好要搞奇数个,最少也应该是3个(和选举机制有关)

使用docker搭建环境

类似下图的结构,按理说这6个节点要在6个不同的服务器主机上的,此时只有一个云服务器,就在一个云服务器上,来完成这里的环境搭建(在工作中,把上述节点放到一个服务器上,是没有意义的)

由于这些节点有点多,相互之间依赖的端口号/配置文件/数据文件可能会冲突,如果直接部署,就需要小心翼翼的取避开这些冲突-使用docker就可以有效避免上述问题

虚拟机,通过软件,在一个电脑上模拟出另外的一些硬件(构造了另一个虚拟的电脑),虚拟机这样的软件,就可以使用一个电脑,来模拟出多个电脑的情况;但是虚拟机比较吃配置

docker可以认为是一个轻量级“虚拟机”,起到了虚拟机这样的隔离环境的效果,但是又没有吃很多的硬件资源,即使是配置比较拉跨的云服务器,也能构造出好几个这样的虚拟环境

  • 安装docker和docker-compose

docker中关键概念“容器”,每一个容器都可以看做一个轻量级的虚拟机

docker-compose 的安装

# ubuntu
apt install docker-compose
# centos
yum install docker-compose
  • 停⽌之前的 redis-server
# 停⽌ redis-server
service redis-server stop
# 停⽌ redis-sentinel 如果已经有的话.
service redis-sentinel stop

  • 使⽤ docker 获取 redis 镜像
 docker pull redis:5.0.9
#类似于git clone从远程仓库拉取代码

docker中的“镜像”和“容器”类似于“可执行程序“和”进程“的关系;镜像可以自己创建,也可以直接拿别人已经构建好的,docker hub(类似于Github)包含了很多其他大佬构建好的镜像

拉取到的镜像,里面包含一个精简的Linux操作系统,并且上面会安装redis,只要直接基于这个镜像创建一个容器跑起来,此时redis服务器就搭建好了

docker-compose来进行容器编排,此处涉及到多个redis-server也有多个redis哨兵节点,每一个redis-server或者每一个redis哨兵节点都是作为一个单独的容器了(6个容器)

通过一个配置文件,把具体要创建哪些容器,每个容器运行的各种参数,描述清楚,后续通过一个简单的命令,就能够批量的启动/停止这些容器了

使用yml这样的格式来作为配置文件,spring也是使用yml来作为配置文件的

  • 创建三个容器,作为redis的数据节点(一主两从)
  • 创建三个容器,作为redis的哨兵节点

其实也是可以用一个yml文件,直接启动6个容器;如果把这6个容器同时启动,可能是哨兵先启动完成,数据节点后启动完成,哨兵可能就会先认为是数据节点挂了,虽然对于大局不影响,但是会影响到观察执行日志的过程

version: '3.7'
services:
#名字是自己起的
 master:
#基于哪个镜像创建的
 image: 'redis:5.0.9'
 container_name: redis-master
#是否自动重启
 restart: always
 command: redis-server --appendonly yes
 ports:
#端口映射,也就是隧道
#也就是XShell中的隧道命令
#宿主机的端口:容器内部的端口
 - 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
#这里格式似乎不太正确 请大家自行抄下面的


version: '3.7'
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


  •  启动所有容器
docker-compose up -d
#-d表示后台运行

此步骤一定要把redis三个服务器彻底关闭,不然无法运行成功 

 ​​​​​​

此处启动的redis就是容器中的redis 

  • 查看运⾏⽇志
docker-compose logs

redis哨兵节点是单独的redis服务器进程

  • 在redis-sentienl中写docker-compose.yml文件
version: '3.7'
services:
#搞三个哨兵节点,并且是奇数个,以利于选举机制
  sentinel1:
    image: 'redis:5.0.9'
    container_name: redis-sentinel-1
#当前节点能够自动启动
    restart: always
#使用后面的软件来启动
    command: redis-sentinel /etc/redis/sentinel.conf
    volumes:
#映射文件,将配置文件映射到/etc/redis/sentinel.conf
#哨兵节点,会在运行过程中,对配置文件进行自动的修改,因此就不能拿一个配置文件,给三个容器分别映射
      - ./sentinel1.conf:/etc/redis/sentinel.conf
    ports:
#端口映射:docker核心功能
      - 26379:26379
  sentinel2:
    image: 'redis:5.0.9'
    container_name: redis-sentinel-2
    restart: always
    command: redis-sentinel /etc/redis/sentinel.conf
    volumes:
      - ./sentinel2.conf:/etc/redis/sentinel.conf
    ports:
      - 26380:26379
  sentinel3:
    image: 'redis:5.0.9'
    container_name: redis-sentinel-3
    restart: always
    command: redis-sentinel /etc/redis/sentinel.conf
    volumes:
      - ./sentinel3.conf:/etc/redis/sentinel.conf
    ports:
      - 26381:26379
  • 创建配置⽂件

创建 sentinel1.conf sentinel2.conf sentinel3.conf . 三份⽂件的内容是完全相同 的,都放到 /root/redis-sentinel/ ⽬录中.

bind 0.0.0.0
#允许其他节点来访问
port 26379
#容器内部端口号
sentinel monitor redis-master redis-master 6379 2
#让当前的哨兵节点监控哪个redis服务器,redis-master本来是IP,但是docker会自动进行域名解析
#6379为端口号,2是法定票数(达到法定票数就可以判定redis主节点挂了)
sentinel down-after-milliseconds redis-master 1000
#down-after-milliseconds明确心跳包的超时时间,设定1000ms之内,如果不返回,就认为挂了,此时投票

报错:哨兵节点不认识redis-master,redis-master相当于一个域名,docker会进行域名解析;docker-compose一下启动了N个容器,此时N个容器处于同一个“局域网”中,可以使这N个容器之间可以相互访问,三个redis-server节点是一个局域网,三个哨兵节点是另一个局域网,默认情况下,这俩网络不是互通的

解决方案:使用docker-compose 把此处的两组服务放到同一个局域网中

docker network ls

  • 在docker-compose.yml中加入配置局域网
networks:
  default:
    external:
      name: redis-data_default

Question:是否可以把6个容器,都写到同一个yml配置中,一次全都启动,不就保证互通问题了吗?


Answer:如果使用这种方案,由于docker-compose启动容器的顺序不确定,就不能保证redis-server一定是在哨兵之前启动的,分成两组就可以保证上述顺序,观察到的日志是比较可控的

在sentinel1.conf文件中产生了新的内容,这些内容都是哨兵节点启动之后,自动进行修改的

哨兵节点的作用演示

哨兵存在的意义,能够在redis主从结构出现问题的时候(比如主节点挂了),此时哨兵节点就能够自动的帮我们重新选出一个主节点,来代替之前挂了的节点,保证整个redis仍然是可用状态

手动把主节点干掉

当主节点挂了之后,哨兵节点开始工作

  • sdown:主观下线,本哨兵节点,认为该节点挂了
  • odown:客观下线,好几个哨兵都认为该节点挂了,达成了一致(法定票数)

此时,主节点挂了这个事情就被实锤了

此时就需要哨兵节点选出一个从节点,作为新的主节点,此处就需要提拔出一个新的主节点

即使原主节点启动,也是作为从节点

主从切换的具体流程

哨兵重新选取主节点的流程

  • 主观下线:哨兵节点通过心跳包,判定redis服务器是否正常工作,如果心跳包没有如约而至,就说明redis服务器挂了,此时还不能排除网络波动的影响,因此就只能是单方面认为这个redis节点挂了
  • 客观下线:多个哨兵都认为主节点挂了(认为挂了的哨兵节点数目达到法定票数),哨兵们就认为这个主节点是客观下线

Question:是否有可能出现非常严重的网络波动,导致所有的哨兵都联系不上redis主节点,误判成挂了呢?

当然是有的,如果出现这个情况,怕是用户的客户端也连不上redis主节点了,此时这个主节点基本也就无法正常工作了

  • 要让多个哨兵节点,选出一个leader,由这个leader负责选一个从节点作为新的主节点

日志中可以看到

三个哨兵节点id

  • 一号哨兵立即给自己投了一票
  • 二号哨兵也立即给了一号哨兵投了一票
  • 三号哨兵也立即给了二号哨兵投了一票
redis-sentinel-1  | 1:X 15 Aug 2024 04:10:18.300 # +vote-for-leader 8727c0b46d6aaaee1d5f00ef3ef100e81e73de34 1
redis-sentinel-1  | 1:X 15 Aug 2024 04:10:18.301 # bbd99057b11998a9d52786d2164eaecfaae64441 voted for bbd99057b11998a9d52786d2164eaecfaae64441 1
redis-sentinel-1  | 1:X 15 Aug 2024 04:10:18.308 # 72f040cb2884e70c8a5faa3c7d0baad4da53fce5 voted for 8727c0b46d6aaaee1d5f00ef3ef100e81e73de34 1

每个哨兵手里只有一票,当哨兵1第一个发现客观下线之后,就立即给自己投了一票,并且告诉2,3,我来负责这个事情;2 3反应慢了半拍,才发现是客观下线,一看1乐意负责这个事情,立即投了赞成票(如果总的票数超过哨兵总数的一半,选举完成了->把哨兵个数设置为奇数个节点,就是为了方便投票)

leader选主节点

  • 此时leader选举完毕,leader就需要挑选一个从节点,作为新的主节点
  1. 优先级:每个redis数据节点,都会在配置文件中,有一个优先级的设置,slave-priority,优先级高的从节点就会胜出
  2. offset:offset最大,就胜出,offset从节点从主节点这边同步数据的进度,数值越大,说明从节点的数据和主节点就越接近
  3. run id:每个redis节点启动的时候随机生成的一串数字(大小全凭缘分)

把新的主节点指定好了之后,leader就会控制这个节点,执行slaveof no one,成为master,再控制其他节点,执行slaveof,让这些其他节点,以新的master作为主节点了

先选leader,再选主节点

小结

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

⼀些注意事项

  • 哨兵节点不能只有⼀个. 否则哨兵节点挂了也会影响系统可⽤性
  • 哨兵节点最好是奇数个. ⽅便选举 leader, 得票更容易超过半数
  • 哨兵节点不负责存储数据. 仍然是 redis 主从节点负责存储
  • 哨兵 + 主从复制解决的问题是 "提⾼可⽤性", 不能解决 "数据极端情况下写丢失" 的问题
  • 哨兵 + 主从复制不能提⾼数据的存储容量. 当我们需要存的数据接近或者超过机器的物理内存,这样的结构就难以胜任了.
  • 为了能存储更多的数据, 就引⼊了集群.

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

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

相关文章

uniapp加载第三方字体方案对比(附原生微信小程序方案)

文章目录 官方文档uniapp文档微信小程序文档 下载字体包引入方案限制微信小程序限制uniapp的限制 方案对比方案1:CSS本地加载方案2:CSS远程加载方案3:转换为base64,然后通过css引入方案4:使用uni.loadFontFace() 页面使…

手撕初阶数据结构之---排序

1.排序概念及运用 排序:所谓排序,就是使⼀串记录,按照其中的某个或某些关键字的⼤⼩,递增或递减的排列起来的操作。 常见的排序算法 直接插入排序的时间复杂度是O(N^2) 这个是最差的情况下,就是大的在前面&#xff…

30kw 可调恒流电子负载,你了解多少?

30kW可调恒流电子负载,是一种用于测试电源、蓄电池、发电机等电力设备的设备。它的主要功能是模拟实际负载,通过调节电流的大小,来检测电力设备的工作性能和稳定性。 让我们了解一下什么是电子负载。电子负载是一种可以吸收或提供电能的设备&…

【数据分析---偏企业】 Excel操作

各位大佬好 ,这里是阿川的博客,祝您变得更强 个人主页:在线OJ的阿川 大佬的支持和鼓励,将是我成长路上最大的动力 阿川水平有限,如有错误,欢迎大佬指正 Excel操作前 必看 Python 初阶 Python—语言基础与…

[MRCTF2020]套娃 php字符串解析绕过,jsfuck编码

进来看到代码 <!-- //1st $query $_SERVER[QUERY_STRING];if( substr_count($query, _) ! 0 || substr_count($query, %5f) ! 0 ){die(Y0u are So cutE!); }if($_GET[b_u_p_t] ! 23333 && preg_match(/^23333$/, $_GET[b_u_p_t])){echo "you are going to th…

超维室外轮式巡检机器人打造无人值守变电站

变电站是电力系统的重要组成部分&#xff0c;负责电能的转换、分配和传输&#xff0c;确保电力供应的稳定性和安全性。然而&#xff0c;由于变电站内设备众多、环境复杂、风险较高&#xff0c;传统的人工巡检方式面临着效率低下、成本高昂和人员安全隐患等问题。为应对这些挑战…

苹果iOS 18 Beta 6更新亮点一览:这些新功能让你爱不释手

苹果公司作为全球科技行业的领军者&#xff0c;每一次的系统更新都备受业界和消费者的关注。 iOS系统作为苹果设备的核心&#xff0c;其每一次迭代都带来了新功能和优化&#xff0c;极大地提升了用户体验。2024年8月13日&#xff0c;苹果向iPhone用户推送了iOS 18 Beta 6更新&…

水印去除方法

有一批建筑图去水印&#xff0c;水印的位置基本位于左右下角或者图片中间&#xff0c;因此调研一些去水印的方法&#xff0c;以前做电商图场景的水印去除或者印章去除的话&#xff0c;通常会训练一个unet来做这个事情。 1.工具 3 秒去水印&#xff01;6 款超好用的免费图像去…

Endnote与word关联 解决方案: COM加载项-----》CWYW插件安装

1、首先说一下本次情况&#xff0c;office的版本是2019&#xff0c;后安装的Endnote 9。旧版word也可按此方法尝试。 2、先找到关键的EndNote Cwyw.dll文件。应在此目录下&#xff1a;C:\Program Files (x86)\EndNote X7\Product-Support\CWYW。 3、如没有EndNote Cwyw.dll文…

DETR论文,基于transformer的目标检测网络 DETR:End-to-End Object Detection with Transformers

transformer的基本结构: encoder-decoder的基本流程为&#xff1a; 1&#xff09;对于输入&#xff0c;首先进行embedding操作&#xff0c;即将输入映射为向量的形式&#xff0c;包含两部分操作&#xff0c;第一部分是input embedding&#xff1a;例如&#xff0c;在NLP领域&…

DevEco Studio 5.0 Beta版下载链接

最新工具 - 下载中心 - 华为开发者联盟 (huawei.com)https://developer.huawei.com/consumer/cn/download/

代码随想录算法训练营第十三天

day12周日放假 二叉树理论基础: 文章链接:代码随想录 文章摘要: 满二叉树定义&#xff1a;如果一棵二叉树只有度为0的结点和度为2的结点&#xff0c;并且度为0的结点在同一层上&#xff0c;则这棵二叉树为满二叉树。 完全二叉树定义&#xff1a;在完全二叉树中&#xff0c…

springboot限流验证码登录接口(优雅版)

我们的业务逻辑是如图所示&#xff0c; 限流思路 我们 实现登录接口之后&#xff0c;我们想像这么一个场景&#xff0c;因为我们的登录接口在我们的拦截器中是放行的&#xff0c;如果这时候有人恶意来爆刷我们的登录接口&#xff0c;那我们的这个接口不就爆掉了吗&#xff0c…

【车载开发系列】使用J-Flash下载Hex文件

【车载开发系列】使用J-Flash下载Hex文件 【车载开发系列】使用J-Flash下载Hex文件 【车载开发系列】使用J-Flash下载Hex文件概要1. 打开J-Flash软件2. 创建新的工程3. 选择芯片类型4. 打开HEX文件5. 连接芯片6. 擦除目标扇区&#xff08;可选&#xff09;7. 烧写文件到目标扇区…

计算机毕业设计PySpark+Django农产品推荐系统 农产品爬虫 农产品商城 农产品大数据 农产品数据分析可视化 PySpark Hadoop

本科生毕业实习与设计&#xff08;论文&#xff09; 基于协同过滤的农产品推荐系统 Agricultural products recommendation system based on Collaborative filtering 学 院&#xff1a; 机械工程学院&#xff08;楷体_GB2312四号&#xff0c;下同&#xff09; …

pdf怎么转换成word?介绍6个pdf转word免费方法!(超简单)

pdf怎么转换成word&#xff1f;pdf格式因兼容多种平台和操作系统而广受欢迎&#xff0c;非常适合文档存储和共享。然而&#xff0c;编辑 PDF 文件通常需要试用一些其它的软件进行辅助&#xff0c;这让许多用户选择将 PDF 转换为 Word 格式&#xff0c;以方便内容修改。在以下情…

《Kotlin核心编程》2021版复习记录

目录 0 前言1 基础语法1.1 数据类型1.2 数组1.3 集合1.4 遍历数据和集合1.5 函数声明返回值类型1.6 var 和 val 2 高阶函数和lambda表达式2.1 高阶函数2.2 方法和成员引用2.3 链式调用2.4 扩展函数2.5 面向表达式编程2.5.1 when表达式2.5.2 for循环2.5.3 in 2.6 字符串相等 3 面…

【nginx 第一篇章】认识一下 NGINX 服务器

一、简介 Nginx (engine x) 是一个高性能的 HTTP 和反向代理服务器&#xff0c;也是一个 IMAP/POP3/SMTP 代理服务器。由俄罗斯程序员 Igor Sysoev 开发&#xff0c;并在2004年首次公开发布。Nginx 以其高并发处理能力、低内存消耗、稳定性、丰富的功能集、简单的配置以及低学…

硬件面试经典 100 题(31~50 题)

31、多级放大电路的级间耦合方式有哪几种&#xff1f;哪种耦合方式的电路零点偏移最严重&#xff1f;哪种耦合方式可以实现阻抗变换&#xff1f; 有三种耦合方式&#xff1a;直接耦合、阻容耦合、变压器耦合。直接耦合的电路零点漂移最严重&#xff0c;变压器耦合的电路可以实现…