Redis 哨兵简介

哨兵(Sentinel)是一个分布式的系统,一个架构中可以运行多个哨兵进程,他们之间使用gossip protocols来进行通信,它为Redis提供了高可用的方案,主要是通过管理多个Redis服务器来完成以下三个任务。

  1. 监控(Monitoring), 哨兵会定期检查主服务器和从服务器的运作是否正常。
  2. 提醒(Notification), 某个Redis服务器出现问题的时候,会主动发出通知
  3. 自动故障迁移(Automaticfailover),当监控的主服务器失效时,哨兵会进行自动故障迁移,将某一个从服务器升级为主服务器,使得新主服务器能够代替失效的服务器。

哨兵机制

哨兵部署


上图是一份典型的Reids部署方式,部署哨兵时一般都会部署三个及以上的哨兵,其原因是哨兵是保护Redis不出现单点故障的机制,如果哨兵只部署1个,那么哨兵自己就成为了单点;如果部署两个哨兵,那么master出现故障的时候,哨兵之间必须约定好谁来执行主从切换,这就涉及到选举的问题了,而两个哨兵之间是无法完成选举的。所以哨兵的个数需要大于等于三个,且最好是奇数。

再来看一份哨兵启动的典型配置文件


// 监控一个名称为 mymaster的Redis 主服务器,其 ip 127.0.0.1 端口 6379  quorum 2
sentinel monitor mymaster 127.0.0.1 6379 2  // 如果哨兵在60s内没收到mymaster的有效ping回复,则认为该master处于down状态, 即主观下线
sentinel down-after-milliseconds mymaster 60000// mymaster 自动故障迁移超时时间为 180s
sentinel failover-timeout mymaster 180000 // 下面的配置和上面一致,只是换了 地址、名字 和 quorum
sentinel monitor quest 192.168.1.3 6380 4sentinel down-after-milliseconds quest 10000sentinel failover-timeout quest 180000

其中,quorum 在哨兵中会有两处用到:

  1. 当哨兵在一定时间内没有收到其监控的主服务器的有效ping回复的话,哨兵会认为该服务器处于主观下线状态,当quorum 配置成2 的话,就是说明当至少有2个哨兵认为该主服务器处于主观下线状态的时候,该主服务器就被认为是客观下线状态。
  2. 当主从切换开始之后,哨兵之间会进行选举,选举出一个主哨兵进行主从切换,当quorum配置成4的话,说明一个哨兵至少需要4票才能成为主哨兵。

在这份配置中,我们可以看到只是设置了一下需要监控的服务器地址和一些必要的参数,并没有涉及从服务器(Redis Slave)以及其他哨兵的配置。那么从服务器和其他哨兵是如何被发现的呢。

哨兵执行流程

哨兵的启动

首先,通过下述方式可以启动一个哨兵

redis-server sentinel.conf --sentinel

启动哨兵后,哨兵会根据配置进行一系列的初始化,然后连接对应的主服务器。哨兵会与主服务器建立两条连接,一条命令连接,一条订阅连接(也可以成为消息连接),

如上图,各个启动的哨兵都于主服务器建立了两条连接,其中虚线是命令连接,实线是订阅连接。订阅连接建立后,哨兵会订阅Redis服务的__sentinel__::hello频道。

哨兵的定时任务

在命令连接上,哨兵会向主服务器发送命令,以完成定时监控的任务

  1. info命令的采集
    每一个哨兵都会每隔10s向连接的服务器都发送info命令,以此采集其服务器信息以及节点拓扑结构。所以配置的时候,只配置了主服务器的地址信息。之后从服务器信息可以通过info命令获得。

当收到info命令的回包后,会与未建立连接的其他从服务器也分别建立命令连接和订阅连接

  1. 哨兵信息的发布
    每个哨兵会在每2s会通过命令连接向主节点和从节点的频道内发布一条信息,从前向后的格式依次如下
字段名 字段意义
sentinel_ip 哨兵IP
sentinel_port 哨兵端口
sentinel_runid 哨兵ID
current_epoch 当前纪元(用于选角和主从切换)
master_name master的名称
master_ip master的ip
master_port master的端口
master_config_epoch master的纪元(用于选举和主从切换)

每个哨兵都会通过订阅连接接收到这条发布的消息,可以根据里面的字段确定是否是新加入的哨兵,以及其ip地址,如果是新加入的哨兵,所有哨兵都会与它进行连接,不过与服务器连接不同,哨兵之间只会建立命令连接。

  1. ping命令
    哨兵会每1s向所有其他哨兵、所有的redis服务器发送ping命令用于心跳检测,如果该命令在有效时间内为得到回复,则会被该哨兵认为是主观下线。这个命令也是哨兵节点用来判断节点是否正常的重要依据

主从切换

再提一次两个概念,主观下线和客观下线

主观下线: 前面有提到过了,只有在一定时间内没有收到ping命令的回复,则发出ping命令的哨兵会认为对应的主服务器节点下线,这就是主观下线。一定时间是在配置中的down-after-milliseconds字段。

客观下线:当超过一定数量的哨兵认为主服务器节点处于主观下线状态的话,那么该主服务器节点就会被认为是客观下线。这边的一定数量是在配置中的quorum 字段。

当主服务器节点处于主观下线阶段,为了保证Redis的高可用性,哨兵就会开始主从切换流程。

主从切换状态

先定义主从切换间的几个状态

状态名 状态值 意义
SENTINEL_FAILOVER_STATE_NONE 0 没发生主从切换
SENTINEL_FAILOVER_STATE_WAIT_START 1 等待开始主从切换,(哨兵之间正在选择主节点)
SENTINEL_FAILOVER_STATE_WAIT_SELECT_SLAVE 2 选择一台从服务器作为新的主服务器节点
SENTINEL_FAILOVER_STATE_SEND_SLAVEOF_NOONE 3 将选择的服务器提升成主服务器节点
SENTINEL_FAILOVER_STATE_WAIT_PROMOTION 4 等待被选中的服务器上报状态
SENTINEL_FAILOVER_STATE_RECONF_SLAVES 5 将其他Slave的同步数据服务器切换为新的主服务器
SENTINEL_FAILOVER_STATE_UPDATE_CONFIG 6 重置主服务器节点的IP端口为新的主服务器

而整个主从切换的状态转换图如下

主从切换流程

  1. 初始状态时,系统的状态如下

  2. 当一个哨兵发现主节点处于主观下线阶段时,会将自身状态切换从SENTINEL_FAILOVER_STATE_NONE 切换到SENTINEL_FAILOVER_STATE_WAIT_START ,并且将当前选举纪元加1,并开始给其他哨兵发送投票命令,让其他哨兵给自己投票。当从哨兵中选举出主哨兵之后,接下来的操作都会由该主哨兵进行。

  3. 主哨兵选择出来后,主哨兵会将自己的状态切换到SENTINEL_FAILOVER_STATE_WAIT_SELECT_SLAVE ,然后开始挑选一台从服务器作为主服务器,挑选规则如下:
    1) 如果该Slave处于主观下线中,则不能被选中
    2) 如果该Slave与主服务器断开时间过长,则不能被选中
    3) 如果该Slave的slave-priority为0,则不能被选中,该字段可以在配置中设置,配置值需要是正整数且越小优先级越高。
    4) 选择优先级最高的Slave,如果优先级相同,则选择具有较大复制偏移量的;如果偏移量也相同,则按字母序选择

  4. 选中下一台主服务器后,主哨兵会将状态切换到SENTINEL_FAILOVER_STATE_SEND_SLAVEOF_NOONE ,并向Slave发送如下命令

    MULTI
    SLAVEOF NO ONE  //  关闭该从服务器的复制功能,将其提升称为一个主服务器
    CONFIG REWRITE // 重写配置
    CLIENT KILL TYPE normal  // 断开当前连接的客户端,客户端会触发重连,重连时会得到新的主服务器地址
    EXEC
    

    发送完命令后,哨兵会将自己的状态切换到 SENTINEL_FAILOVER_STATE_WAIT_PROMOTION。

  5. 哨兵切换到SENTINEL_FAILOVER_STATE_WAIT_PROMOTION 后,会再下一次info命令的时候检查对应从服务器的role字段,如果role是master的话,则说明从服务器已经变更了自己的角色,成为了主服务器,这时哨兵的状态就会切换到SENTINEL_FAILOVER_STATE_RECONF_SLAVES ,并将其他从服务器发送切换主服务器的命令,命令如下

    MULTI
    SLAVEOF IP PORT // 指明该从服务器应该向对应IP:PORT同步数据
    CONFIG REWRITE  // 配置重写
    CLIENT KILL TYPE normal  //  断开当前连接的客户端,客户端会触发重连,重连时会得到新的主服务器地址
    EXEC
    

  1. 当所有其他从服务器更新完后,哨兵会将状态切换到SENTINEL_FAILOVER_STATE_UPDATE_CONFIG ,这个步骤中,主哨兵会将原先下线的主服务器切换到当前新的主服务器,然后将原先的主服务器变更成当前主服务器的从服务器。

  2. 完成上述所有步骤后,主哨兵会将状态切换到SENTINEL_FAILOVER_STATE_NONE,至此,主从切换完成。

一些问题

通过上述对主动切换的介绍,思考以下问题

  1. 主从切换完成后,其他哨兵如何知道现在提供服务的主节点时哪个?
  2. 如果执行主动切换的主哨兵在中途发送故障了,切换操作是否会由其他哨兵继续呢?
  3. 故障的master恢复之后,是否还能继续提供服务呢?

答案放在文末,就不和问题放在一起了

参考

  1. https://www.cnblogs.com/Eugene-Jin/p/10819601.html Eugene_Jin
  2. https://blog.csdn.net/yswKnight/article/details/78158540 詠聖wK
  3. https://www.cnblogs.com/kevingrace/p/9004460.html 散尽浮华
  4. 《Redis5 设计与源码分析》 陈雷

问题答案

  1. 其余哨兵可以通过subscribe sentinel::hello 频道知道当前提供服务的主节点的IP和端口
  2. 执行哨兵发生故障后,其他哨兵会重新从选举哨兵开始流程
  3. 宕机的主节点恢复后会作为新的主节点的从节点提供服务

Redis - 哨兵机制与主从切换相关推荐

  1. Redis哨兵模式实现主从切换

    redis简介: Redis是一个开源的内存中的数据结构存储系统, 它可以用作:数据库.缓存和消息中间件 为什么要使用redis? 性能和并发 #性能? 我们在碰到需要执行耗时特别久,且结果不频繁变动 ...

  2. Redis哨兵机制以及发布订阅

    Redis哨兵机制 1 哨兵Sentinel机制 2 哨兵架构原理 3 搭建哨兵架构 4 通过springboot操作哨兵 Redis发布订阅 1 哨兵Sentinel机制 Sentinel(哨兵)是 ...

  3. Redis哨兵机制 哨兵集群搭建

    本文讲解,基于Redis版本:5.0.3  2021-12-24更新:本教程 Redis-6.2.1 同样适用 本文是在Redis集群的基础之上,通过Redis哨兵机制来完成Redis集群的高可用方案 ...

  4. Redis——Redis哨兵机制原理

    摘要 redis的主从复制是redis系统的高可用前提,从库宕机依然可以将请求发送给主库或者其他从库,但是 Master 宕机,只能响应读操作,写请求无法再执行.所以主从复制架构面临一个严峻问题,主库 ...

  5. redis 哨兵机制环境搭建 - 七脉 - 博客园

    原文地址 Redis哨兵机制,一主二从 注:Redis哨兵切换,建议一主多从 一.一主二从 教程步骤:https://www.cnblogs.com/zwcry/p/9046207.html 二.哨兵 ...

  6. 什么是Redis哨兵机制?

    写在前面 之前有位朋友去面试被问到Redis哨兵机制,这道题其实很多小伙伴都应该有被问到过!本文将跟大家一起来探讨如何回答这个问题!同时用XMind画了一张导图记录Redis的学习笔记和一些面试解析( ...

  7. Redis集群的主从切换研究

    目录 目录 1 1. 前言 1 2. slave发起选举 2 3. master响应选举 5 4. 选举示例 5 5. 哈希槽传播方式 6 6. 一次主从切换记录1 6 6.1. 相关参数 6 6.2 ...

  8. php redis主从自动切换,Redis 集群的主从切换

    Redis 集群的主从切换不再使用 Sentinel 作为外置监控, 而是集群内部在主节点挂掉之后选举出一个从节点取代主节点, 处理相应的分片的数据请求. 当然前提条件是对应的主节点有至少一个可连通的 ...

  9. php 连接redis哨兵,Redis哨兵模式实现主从故障互切换的方法

    Redis Sentinel 是一个分布式系统, 你可以在一个架构中运行多个 Sentinel 进程(progress), 这些进程使用流言协议(gossip protocols)来接收关于主服务器是 ...

最新文章

  1. css 不展示滚动条,CSS-界面滚动时不显示滚动条
  2. the archive which is referenced by ...问题解决方案
  3. 利用python绘制雪景图_python绘制雪景图
  4. 第 6 章 本地方法接口
  5. POJ 2886 能被3除尽的数之和
  6. 变量、属性、函数、方法总结
  7. linux禁用ssh弱加密算法,SSHSSL弱加密算法漏洞修复
  8. Nginx源码分析 - HTTP模块篇 - HTTP模块的阶段处理PHASE handler(23)
  9. 【servlet】servlet基础知识总结
  10. 190301每日一句
  11. 怎么使用ABBYY中的Bates编号
  12. java与xml转换 -- XStreamAlias
  13. 微信农场,第二个QQ秀?
  14. 【总结】1147- 一文吃透 Webpack 核心原理
  15. antd 自定义表单验证 onBlur
  16. WSL:关闭WSL【vmmem 进程占用CPU资源的解决办法】
  17. 使用mybatis的逆向工程易出现的错误
  18. [ROC-RK3568-PC] 手把手教你把出厂的Android系统烧写为Ubuntu系统
  19. 用Requests下载百度一页图片,以下载芳心纵火犯为例
  20. CC2540开发入门

热门文章

  1. 自定义 behavior - 完美仿 QQ 浏览器首页,美团商家详情页
  2. 火星车开发板”SDR Receiver分析说明
  3. 全面理解-Flutter(万字长文,【性能优化实战】
  4. 计算机专业推荐的比赛
  5. CentOS7下使用YUM安装MySQL5.6
  6. Android即时通讯--仿QQ即时聊天:(一)初识Socket
  7. 随笔 - 58, 文章 - 0, 评论 - 0, 引用 - 0 三次握手 四次握手 与socket函数的关系
  8. JDK JRE JVM ===》JavaSE 标准版
  9. 拉格朗日插值法与牛顿插值多项式
  10. docx4j生成Word添加页眉页脚水印 页眉页脚奇偶显示首页显示