2023.1.23 关于 Redis 哨兵模式详解

news2024/9/28 21:46:29

目录

引言

人工恢复主节点故障

​编辑

主从 + 哨兵模式

Docker 模拟部署哨兵模式

关于端口映射 

展现哨兵机制

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

哨兵模式注意事项


引言

人工恢复主节点故障

1、正常情况

2、主节点宕机

3、程序员主动恢复

  1. 先看看该主节点还能不能抢救
  2. 如果不好定位主节点是啥原因挂的,或知道原因,但是短时间难以解决,此时便需要挑一个从节点,将其设置为新的主节点

a)将选中的从节点,通过 slaveof no one 命令解除之前的主从关系

b)其他的从节点,通过修改 slaveof 命令,将 ip 和 port 改为新上任的主节点

c)告知客户端(修改客户端配置)让客户端能够连接新的主节点,用来完成修改数据的操作

d)原先挂掉的主节点修好后,将其作为一个新的从节点,挂到这组机器中


小总结:

  • Redis 主从复制模式下,主节点故障后需要进行的人工工作是比较繁琐的
  • 如果这个操作过程如果出错,可能会导致问题愈发严重
  • 通过人工干预的做法,就算程序员第一时间看到了报警信息,第一时间处理,恢复的过程也至少需要 半小时 以上
  • 在这期间,整个 Redis 一直不能进行写操作!

注意:

  • 实际开发过程中,对于服务器后端开发,监控程序是非常重要的!

原因:

  • 服务器需具有高可用性,因为其 7*24 小时不间断运行
  • 服务器长期运行总会有一些 意外,同时我们也难以预料具体啥时候会出现意外
  • 总不可能全靠人工来不间断盯着服务器运行吧!

解决方案:

  • 写一个程序,用监控程序来盯着服务器的运行状态
  • 监控程序用于发现 服务器的运行是否出现状态异常
  • 监控程序往往还需搭配 报警程序 一起使用
  • 给程序员报警,通过短信/电话/邮件/微信/钉钉等,通知程序员该服务器程序出现异常

  • 本文主要详解 Redis 部署方式中的主从 + 哨兵模式

主从 + 哨兵模式

  • 如上图所示,此处提供了多个单独的 redis sentinal 进程
  • 这三个哨兵进程会监控现有的 Redis 主节点 和 从节点

注意点一:

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

具体流程:

  1. 当一个哨兵节点发现主节点挂了时,还不够,还需要多个哨兵节点来共同认定这件事(主要是为了防止误判)
  2. 如果主节点确实挂了,便会在这些哨兵节点中推举出一个 leader,由这个 leader 负责从现有的从节点中挑选一个作为新的主节点
  3. 挑选出新的主节点后,哨兵节点便会自动控制被选中的节点,执行 slaveof no one 命令,并且控制其他从节点修改 slaveof 到新的主节点上
  4. 最后哨兵节点会自动通知客户端程序,告知新的主节点是谁,以便后续客户端再进行写操作时,可直接针对新的主节点进行操作

Redis 哨兵核心功能:

  1. 监控
  2. 自动的故障转移
  3. 通知

注意:

  • 虽然可以仅有一个 Redis 哨兵节点,但是相应也会存在一定问题

1、如果哨兵节点只有一个,它自身也容易出现问题

  • 万一这个哨兵节点挂了,后续 Redis 节点也挂了,此时便无法进行自动恢复了

2、出现误判的概率也比较高

  • 比如 网络传输时容易出现抖动或者延迟丢包等

基本的原则:

  • 在分布式系统中,应该避免使用 单点
  • 哨兵节点,最好搞奇数个,最少也应该是 3 个(选举机制)

Docker 模拟部署哨兵模式

  • 此处我们模拟上图进行部署

  • 按理说,这 6个节点需在 6个不同的服务器主机上
  • 但是此时只能在一个 云服务器上完成此处的部署操作

注意点一:

  • 实际工作中,把上述节点放到一个服务器上是毫无意义的!
  • 当前这么做只是条件有限,我仅买了一个云服务器!

注意点二:

  • 由于这些节点还挺多,相互之间容易打架,比如依赖的端口号、配置文件、数据文件等
  • 如果直接部署的话,便需要小心翼翼地避开这些冲突
  • 十分繁琐的同时也会和在不同主机上部署存在较大差异

解决方案:

  • 使用 docker 便可以有效的解决上述的问题
  • docker 中有一个关键概念 ——> 容器
  • 每个容器可看做一个轻量级的虚拟机

 1、安装 docker 和 docker-compose点击下方链接即可跳转安装)

CentOS7 安装 docker 和 docker-compose


2、停止之前的 Redis 服务器


3、使用 docker 获取 Redis 镜像

  • 此处我们通过下方命令,直接从 docker hub 上拉取 redis 5.0.9 的镜像
docker pull redis:5.0.9
  • 使用 docker images 命令查看是否成功拉取镜像

注意点一:

  • docker 中的 镜像 和 容器
  • 类似于 可执行程序 和 进程 的关系

注意点二:

  • 镜像可以自己构建,也可以直接拿别人已经构建好的
  • docker hub 中包含了很多其他大佬们构建好的镜像,其中便有 Redis 官方提供的镜像

注意点三:

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

4、基于 docker 来搭建 redis 哨兵环境

注意点一:

  • 此处涉及到多个 Redis 服务器 ,同时也有多个 Redis 哨兵节点
  • 每个 Redis 服务区 或 每个 Redis 哨兵节点 都作为一个单独的容器(6个容器)
  • 通过配置文件,把具体要创建哪些容器 和 每个容器运行的各种参数 给描述清楚
  • 后续通过一个简单的命令,便能批量的启动 或 停止这些容器了!

注意点二:

  • 此处我们使用 yml 格式来作为配置文件

注意点三:

  • 此处我们创建两个 yml 配置文件
  1. 创建三个容器,作为 Redis 的数据节点(一主两从)
  2. 创建三个容器,作为 Redis 的哨兵节点

问题:

  • 是否可以直接仅用一个 yml 配置文件直接启动上述的 6个容器?
  • 即将 Redis 的数据节点和 Redis 的哨兵节点放到一个配置文件中,然后统一启动或停止

回答:

  • 如果将这 6个容器同时启动,可能是 哨兵节点 先启动完成,数据节点后启动完成
  • 此时哨兵节点便可能会认为数据节点挂了
  • 虽然对于大局不影响,即可以成功启动,但是会影响这些节点的执行过程,从而影响后续日志的观察

注意点四:

  • 为了方便部署,此处我们使用 docker-compose 来进行 容器的编排!

5、配置数据节点的 yml 文件

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

7、启动数据节点

  • 当然我们也可以通过输入 docker-compose logs 命令来查看运行日志信息


8、配置哨兵节点的 yml 文件

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

  • 根据上图所示,需要我们在 redis-sentinel 目录下创建三个 conf 文件 !!
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:
      - ./sentinel1.conf:/etc/redis/sentinel.conf
    ports:
      - 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

 9、创建哨兵节点的三个 conf 配置文件

  • 向三个配置文件中写入相同内容
bind 0.0.0.0
port 26379
sentinel monitor redis-master redis-master 6379 2
sentinel down-after-milliseconds redis-master 1000

注意:

  • 初始情况下,这三个配置文件内容可以是一样的!


10、启动哨兵节点

  • 使用 docker-compose logs 查看日志文件

  • 此处我们可以看到全是报错信息
  • 该哨兵节点,不认识 redis-master
  • redis-master 相当于一个域名,docker 会自动对其进行域名解析

原因:

  • 当使用 docker-compose 启动 N个容器时
  • 此时这 N 个容器均处于同一个局域网中,因此这 N 个容器之间可以相互访问
  • 显然因为 数据节点 和 哨兵节点 并不是同时启动的!
  • 所以 三个数据节点处在一个局域网,三个哨兵节点处在另一个局域网
  • 默认情况下,这俩个局域网之间是不互通的!

实例理解

  • 使用 docker network ls 命令列出当前 docker 中的局域网

  • 此处先启动了 三个数据节点,就相当于自动创建了 第一个局域网
  • 再启动三个哨兵节点,相当于又自动创建了 第二个局域网

解决方案:

  • 可以使用 docker-compose 将此处的两组服务器给放到同一个局域网中
  • 即直接 三个哨兵节点 加入到 三个数据节点的局域网中
  • 而不是让这三个哨兵节点在启动时自动创建第二个局域网

11、在 redis-sentinel 文件下的 docker-compose.yml 配置文件下补充内容

networks:
  default:
    external:
      name: redisdata_default

12、重新哨兵节点的容器

  •  打开 sentinel1.conf 、sentinel2.conf、sentinel3.conf 进行观察


  • 通过上述的操作,就完成了 Docker 模拟部署哨兵模式!

关于端口映射 

  • docker 容器可以理解成是一个轻量的虚拟机
  • 在该容器中,端口号 和 外面宿主机 的端口号为两个体系

实例理解

  • 如果外面宿主机使用了 5000 端口,在容器内部也可以使用 5000 端口
  • 彼此不会冲突

  • 有时候希望在容器外面能够访问到容器内部的端口
  • 此时便需要进行端口映射,将容器里的端口映射到宿主机上
  • 后续访问宿主机的这个端口,就相当于在访问对应容器的对应端口了

  • 三个容器,每个容器内部的端口号都自成一个小天地
  • 即容器1 的 6379 和 容器2 的 6379 之间彼此不会有冲突
  • 可以把两个容器视为两个主机
  • 站在宿主的角度,访问上述几个端口时,也不知道这个端口实际上是一个宿主机上的服务,还是来自于容器内部的服务
  • 只要正常去使用即可

注意:

  • 此处的映射过程非常像 NAT

展现哨兵机制

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

1、这里我们可以通过 docker stop redis-master  命令手动将主节点给干掉

  • 当主节点挂掉之后,哨兵节点便开始工作了!

2、此处我们可以观察哨兵节点的工作日志


3、此处我们连接到被选中的从节点,即新的主节点


4、此时我们重启 原 6379 端口主节点继续观察

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

1、主观下线

  • 哨兵节点通过心跳包,判定 Redis 服务器是否正常工作
  • 如果心跳包没有如约而至,就说明该 Redis 服务器挂了
  • 当然此时并不能排网络波动的影响,因此就只能是单方面认为这个 Redis 服务器挂了

2、客观下线

  • 多个哨兵都认为主节点挂了,即 认为挂了的哨兵节点数目达到法定票数
  • 此时哨兵们便会认为该 主节点为 客观下线

问题:

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

回答:

  • 可能存在!
  • 如果出现该情况,可能用户的客户端也连不上 Redis 主节点了
  • 此时这个主节点基本也无法正常工作了

注意:

  • 挂了 不一定是进程崩了
  • 只要无法正常访问,都可以视为是挂了

3、多个哨兵节点选出一个 leader 节点,由 leader 负责选出一个 从节点 作为新的主节点

  • 每个哨兵手里只有一票
  • 当哨兵1 第一个发现当前为客观下线后,便立即给自己投一票,并且告诉哨兵2 和哨兵3 我来负责这件事
  • 哨兵2 和 哨兵3 反应慢了半拍后发现为客观下线,一看哨兵1 乐意负责这件事,便立即投了赞成票

注意点一:

  • 对于哨兵2 和哨兵3 而言,当它们还未投票时,只要收到拉票请求,便会直接投出该票
  • 即 如果有多个拉票请求,会投给最先到达的

注意点二:

  • 如果总的投票数超过哨兵总数的一半,此时选举便完成了
  • 也正是因为这一点,才建议将哨兵个数设置为奇数个节点,方便投票!

注意点三:

  • 上述投票过程,就是看谁的反应快、谁的网络延时小
  • 谁的反应快,谁就最有可能成为 leader !

4、leader 选举完毕,leader 挑选一个从节点,作为新的主节点

挑选顺序如下:

  1. 优先级: 每个 Redis 数据节点都会在配置文件中,均存在优先级设置(slave-priority),即优先级最高的将成为新的主节点
  2. offset:代表从节点这边同步数据的进度,谁的数值越大,谁的数据和主节点数据就越接近,即 offset 最大的将成为新的主节点
  3. run id:每个 Redis 节点启动时,都会随机生成的一串数字(大小全凭缘分),此时将随机挑选一个成为新的主节点

5、leader 控制选中的节点执行 slave no one 命令成为 master,再控制其他节点,执行 slave of ,让其他节点以新的 master 作为主节点


小总结:

  • 以上是个常见的面试题
  • 尤其是注意选举的过程,不是直接选出新的主节点,而是先选 leader 由 leader 负责后续的主节点指定

哨兵模式注意事项

  1. 哨兵节点不能只有一个,否则哨兵节点挂了也会影响系统可用性
  2. 哨兵节点最好是奇数个,方便选举 leader ,得票更容易超过半数(大部分情况下 3 个足已)
  3. 哨兵节点不负责存储数据,仍然是 Redis 主从节点负责存储(哨兵节点就可以使用一些配置不高的机器来部署,但是不能搞一个机器部署三个哨兵)
  4. 哨兵 + 主从复制解决的问题是 提高可用性,不能解决 数据极端情况下写丢失 的问题
  5. 哨兵 + 主从复制不能提高数据的存储容量,当我们需要存的数据接近或者超过机器的物理内存,这样的结构就难以胜任了

  • Redis 集群就是解决存储容量问题的有效方案

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

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

相关文章

[GDMEC-无人机遥感研究小组]无人机遥感小组-000-数据集制备

基于labelme的无人机语义分割数据集制备 文章目录 基于labelme的无人机语义分割数据集制备1. 数据获取2. 安装labelme3.利用labelme进行标注 1. 数据获取 数据集制备需要利用无人机飞行并采集标注。使用录制模式,镜头垂直向下进行拍摄,得到DJI_XXXX.MP4…

如何实现动态代理(俩种方式)

文章目录 基于接口的动态代理:基于类的动态代理: 基于接口的动态代理: 通过Java的反射机制来动态创建代理对象,代理对象实现了一个或多个接口。 Java提供了java.lang.reflect包中的Proxy类和InvocationHandler接口来实现基于接口…

仰暮计划|“他说,他是出生于两个时代的人”

凌保庆老爷爷,1942年10月4日出生,今年82岁,家住在河南省登封市唐庄乡磨沟村。7月28日,我作为仰暮计划小队的一员去拜访了这位老人,听凌爷爷讲述了他的故事。 走进这户人家的时候,凌爷爷正在书房里。虽然家…

Spring Cloud 系列:基于Seata 实现 XA模式

https://seata.io/zh-cn/docs/user/mode/xa https://seata.io/zh-cn/docs/dev/mode/xa-mode XA 规范 是 X/Open 组织定义的分布式事务处理(DTP,Distributed Transaction Processing)标准,XA 规范 描述了全局的TM与局部的RM之间的…

【深度学习】线性回归模型与梯度下降法

线性回归模型与梯度下降法 线性回归模型与枚举法 线性回归模型定义: w:权重b:偏置#mermaid-svg-ZAxF27Mw5dXNQgw2 {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-ZAxF27Mw5dXNQgw2 .error-icon{fill:#552222;}…

大数据开发之Spark(完整版)

第 1 章:Spark概述 1.1 什么是spark 回顾:hadoop主要解决,海量数据的存储和海量数据的分析计算。 spark是一种基于内存的快速、通用、可扩展的大数据分析计算引擎。 1.2 hadoop与spark历史 hadoop的yarn框架比spark框架诞生的晚&#xff…

JRT的无源码发布

之前介绍过JRT最大的特点就是业务脚本化。老javaer就会说你业务代码都在发布环境放着,那怎么代码保密,在发布环境别人随便改了启不是不安全,或者一些代码我就是不想让人看源码呢。 其实JRT的业务脚本化只是特性,不是代表就必须要…

【域名解析】如何将域名指向对应服务器IP

目录 🌷一、域名解析基本概念 🌼1. 定义 🌼2. 域名解析类型 🌷二、域名解析服务器IP地址 🌼1. 操作步骤 🌼2. 验证 🌷一、域名解析基础知识 🌼1. 基本概念 定义: …

【操作系统】实验八 proc文件系统

🕺作者: 主页 我的专栏C语言从0到1探秘C数据结构从0到1探秘Linux 😘欢迎关注:👍点赞🙌收藏✍️留言 🏇码字不易,你的👍点赞🙌收藏❤️关注对我真的很重要&…

破解不了WIFI?也许你应该试试社工...

以下案例为虚拟环境,请勿模仿 做什么? 由于工作出差在该某某企业出差,手机和电脑都没办法用流量…流量包1G1块…太贵了…我勒个豆啊…发现WIFI密码难以破解(小kali上过了)。 出去逛逛吧…发现楼道有海康威视摄像头,学过交换机的一般都看得出来这个摄像…

jquery多选框

使用hbuilder <!DOCTYPE html> <html><head><meta charset"GBK"><title></title></head><body><table id"myTable"> <tr> <td>黄1</td> </tr> <tr> <td>…

C语言通过IXMLHttpRequest以get或post方式发送http请求获取服务器文本或xml数据

做过网页设计的人应该都知道ajax。 Ajax即Asynchronous Javascript And XML&#xff08;异步的JavaScript和XML&#xff09;。使用Ajax的最大优点&#xff0c;就是能在不更新整个页面的前提下维护数据。这使得Web应用程序更为迅捷地回应用户动作&#xff0c;并避免了在网络上发…

计算机网络——网络层(1)

计算机网络——网络层(1&#xff09; 小程一言专栏链接: [link](http://t.csdnimg.cn/ZUTXU) 网络层&#xff1a;数据平面网络层概述核心功能协议总结 路由器工作原理路由器的工作步骤总结 网际协议IPv4主要特点不足IPv6主要特点现状 通用转发和SDN通用转发SDN&#xff08;软件…

《WebKit技术内幕》学习之十三(3):移动WebKit

3 其他机制 3.1 新渲染机制 为了移动领域更好的用户体验&#xff0c;渲染机制所做的改进主要是提升渲染性能来增加响应的速度&#xff0c;甚至不惜牺牲一些跟规范定义的行为不一致的地方。在这一小节中主要介绍三个方面的技术&#xff0c;其一是Tiled Backing Store&#x…

【LLM】FuseLLM:大模型融合trick-知识融合LLMs

前言 传统的模型融合方法分为集成的方法和权重合并的方法&#xff0c;这两种方法在以往的NLP的比赛中非常常见&#xff0c;是一种提分手段。然而&#xff0c;上述两种方法都需要预训练或者微调相应的模型。在大模型场景下&#xff0c;对每个源模型都进行初始化成本太高&#x…

是用原生js创建红包雨效果

需求: 创建红包雨 答案: // 红包雨代码 开始 // 添加遮罩层 const addOverlay () > {const overlay document.createElement(div);overlay.className overlay;overlay.style.position fixed;overlay.style.top 0;overlay.style.left 0;overlay.style.width 100%;o…

华为机考入门python3--(0)测试题1-句子平均重量

分类&#xff1a;字符串 知识点&#xff1a; 获取输入 input().strip().split(" ") 拼接列表 " ".join(list) 输出指定位数的浮点数 print("%.2f" % value) len() 函数对于很多内置的数据类型都适用&#xff0c;它返回对象的元素个数或长度。…

Qt6入门教程 11:父子对象关系

在上一篇中的纯手写部分&#xff0c;不管是创建菜单、工具栏还是状态栏&#xff0c;我们new完之后都未显式的调用delete进行销毁&#xff0c;这样难道不会有内存泄漏么&#xff1f; QMenuBar *menuBar new QMenuBar(this); QToolBar *toolBar new QToolBar(this); QStatusBa…

yolov8上使用gpu教程

yolov8上使用gpu教程 安装Cuda和Cudnnyolov8上使用gpu 安装Cuda和Cudnn 1.查看支持的cuda版本&#xff0c;并去官网下载。 nvidia-smi2.网址&#xff1a;https://developer.nvidia.com/cuda-toolkit-archive 3.安装细节 安装的前提基础是&#xff0c;有vs的C环境。我电脑有…

GBASE南大通用Connection 构造函数

GBASE南大通用分享  重载列表 1) 初始化一个新的 GBaseConnection 类实例。 GBaseConnection() 2) 当给定连接字符串的时候初始化一个新的 GBaseConnection 类实例。 GBaseConnection(string)  注释 当创建一个新的 GBaseConnection 实例的时候&#xff0c;其属性设…