Redis基础篇(七)哨兵机制
上一篇文章介绍了高可靠方案:主从集群模式。通过主从库的读写分离,来保证服务的可靠性。
当某个从库出现故障时,不影响服务的使用,主库仍然可以处理写命令,其他从库可以处理读命令。但主库发生故障,就不能处理写命令了,从库只能处理读命令。这就影响服务的正常使用了,该如何解决呢?
只要找一个从库当主库就可以解决了。但还有三个问题需要处理:
- 主库真的挂了吗?
- 该选择哪个从库作为主库?
- 怎么把新主库的相关信息通知给从库和客户端?
这里就要介绍Redis的哨兵机制了。哨兵机制指在Redis主从集群模式下,实现主从库自动切换。它有效地解决了主从集群模式下故障时的三个问题。
哨兵机制的基本流程
哨兵其实是一个运行在特殊模式下的Redis进行,主从库实例运行的同时,它也在运行。哨兵主要负责的任务有三个:监牢、选主(选择主库)和通知。如下图所示:
- 监控:哨兵进程周期性地给所有主从库发送PING命令,检测它们是否在线运行
- 选主(选择主库):选出新主库
- 通知:让从库执行replicaof,与新主库同步;通知客户端,与新主库连接。
通知任务相对比较简单且容易理解,但在监控和选主这两个任务中,哨兵需要做出两个决策:
- 在监控任务中,哨兵需要判断主库是否处于下线状态;
- 在选主任务中,哨兵要决定选择哪个从库实例作为主库。
下面就介绍一下这两个任务。
哨兵是如何判断主库是否下线
哨兵对主库的下线状态判断有“主观下线”和“客观下线”两种。
- 主线下线,哨兵发现主库或从库对PING命令的响应超时。
- 客观下线,表示主库下线是一个客观事实。
哨兵在判断主从库采用不同方式:
- 哨兵PING从库,如果超时,就直接标记“主观下线”
- 哨兵PING主库,超时不能直接标记“主观下线”,因为可能由于网络阻塞等原因导致误判。
如何解决哨兵误判?
通过哨兵集群,也就是由多个哨兵组成的集群来进行判断。采用少数服从多数,超过N/2+1判断主库为“主观下线”,那就判断主库为“客观下线”。关于哨兵集群,下面会详细介绍。
哨兵是如何选定新主库的?
哨兵选定新主库用四个字概括:“筛选+打分”。简单来说,就是根据筛选条件选出候选从库,然后通过打分,选出最高分的作为新主库。下面说一下筛选条件和打分规则。
筛选条件
首先从库必须在线运行。
其次从库网络状态良好。从库和主库断连超出一定的阈值就把这个从库筛掉。这个阈值就是down-after-milliseconds
,表示主从库断连的最大连接超时时间。例如发生超过10次,就认定从库的网络状况不好。
关于down-after-milliseconds
,值越小,哨兵就越敏感。当网络拥塞但主库正常,可能会发生不必要的切换。而当主库真的故障了,就切换及时,对业务影响最小。
因此down-after-milliseconds
要设置合适的值,既减少不必要的切换,也保证能够及时切换,降低对业务的影响。
打分规则
第一轮,优先级最高的从库得分高。可通过slave-priority
配置项,设置从库优先级。
第二轮,和旧主库同步程度最接近的从库得分高。很容易理解,越接近主库,说明数据丢失越少。前面介绍主从复制时,已经知道主从库是通过repl_backlog_buffer
保持同步的,所以slave_repl_offset
最接近master_repl_offset
,得分高。
第三轮,ID号小的从库得分高。每个实例都会有一个ID。这是最后一轮,必须决出胜负,所以就选择最小ID的作为新主库。
到这里,我们对哨兵机制的基本流程有了一个整体的认识,下面我们再来了解关于主从切换的两个问题。
在做主从切换时,客户端能否正常地进行请求操作?
如果客户端使用了读写分离,那么读请求不受影响,而写请求会失败。失败持续时间 = 哨兵切换主从的时间 + 客户端感知到新主库的时间。
如果不想让业务感知到异常,那客户端只能把写失败的请求先缓存起来,或者写入消息队列中间件。这种只适合对写入请求返回值不敏感的业务。
应用程序不感知服务中断,哨兵和客户端要做什么?
当哨兵完成主从切换后,客户端需要及时感知到主库发生了变更,然后把缓存的写请求写入到新库中,保证后续写请求不会再受到影响。具体做法有两方面:
一方面是哨兵主要通知客户端。哨兵在选主后,会把新主库的地址写入自己实例的pub/sub里,客户端需要订阅pub/sub。当切换新主库后,客户端就能拿到新主库的地址,把写请求发到这个新主库即可。
另一方面是客户端主动获取最新的主从地址。如果客户端因为某些原因错过了哨兵的通知,或者哨兵通知后客户端处理失败了,就需要客户端主动获取。
下面再来学习哨兵集群。
哨兵集群
如果哨兵实例在运行时发生故障,主从库还能正常切换吗?
通常,我们在解决一个系统问题的时候,会引入一个新机制,或者设计一层新功能。这里Redis引入哨兵集群来解决哨兵实例的高可靠性问题。
基于pub/sub机制组成哨兵集群
哨兵实例之间可以互相发现,靠的是Redis提供的pub/sub机制,也就是发布/订阅机制。
哨兵和主库建立连接,就可以在主库上发布消息了,比如发布自己的连接信息(IP和端口),同时它也会从主库上订阅消息,获得其他哨兵的连接信息。
当多个哨兵实例都在主库上做了发布和订阅操作,它们之间就能知道彼此的IP地址和端口了。
哨兵除了彼此之间建立起连接形成集群外,还需要和从库建立连接。因为在哨兵的监控任务中,它需要对主从库都进行监控,而且在主从库切换完成后,还需要通知从库,让它们和新主库进行同步。
那么,哨兵是如何知道从库的IP地址和端口的呢?
哨兵通过向主库发送INFO命令来完成的。如下图所示:
通过pub/sub机制,哨兵之间可以组成集群;通过INFO命令,哨兵和从库建立连接,并进行监控。
但是哨兵不能只和主、从库连接。因为,主从库切换后,客户端也需要知道新主库的连接信息。所以哨兵还需要把新主库的信息告诉客户端。
还是可以依赖pub/sub机制来完成哨兵和客户端的信息同步。
基于pub/sub机制的客户端事件通知
本质上,哨兵就是一个运行在特定模式下的Redis实例,只完成监控、选主和通知的任务,因此它也具有pub/sub功能。下面是哨兵提供的一些重要的频道。
知道这些频道后,可以让客户端从哨兵这里订阅消息了。
由哪个哨兵执行主从切换?
在哨兵集群模式下,通过“投标仲裁”,选出哨兵Leader来执行主从切换。投标仲裁的流程如下图所示:
任何一个实例判断主库“主观下线”,就会给其他实例发送is-master-down-by-addr命令。
其他实例会根据自己和主库的连接情况,做出Y或N响应。
一个哨兵获得仲裁所需的赞同票数后,就可以标记主库为“客观下线”。这个票数可以通过哨兵配置文件中的quorum配置项来设定。
再给其他哨兵发送命令,表示希望由自己来执行主从切换,并让其他哨兵进行投票。这个也叫“Leader选举”,满足以下两个条件才能当Leader:
- 拿到半数以上的票数
- 拿到的票数>=quorum
小结
- 哨兵机制是实现Redis不间断服务的保证。
- 哨兵机制的三大任务:监控、选主、通知。
- 为了降低误判率,通过采用哨兵集群,并采用“少数服从多数”的原则,判断主库是否客观下线。
- 哨兵集群的关键机制,包括:
- 基于pub/sub机制的哨兵集群组成过程;
- 基于INFO命令的从库列表,这可以帮助哨兵和从库建立连接;
- 基于哨兵自身的pub/sub功能,实现了客户端的哨兵之间的事件通知。
- 哨兵集群在判断了主库“客观下线”后,经过投票仲裁,选举一个Leader来负责主从切换。
最后再分分享一个经验:要保证所有哨兵实例的配置是一致的,尤其是主观下线的判断值down-after-milliseconds。
参考资料
Redis基础篇(七)哨兵机制的更多相关文章
- 《【面试突击】— Redis篇》-- Redis的主从复制?哨兵机制?
能坚持别人不能坚持的,才能拥有别人未曾拥有的.关注左上角编程大道公众号,让我们一同坚持心中所想,一起成长!! <[面试突击]— Redis篇>-- Redis的主从复制?哨兵机制? 在这个 ...
- redis(5)--redis集群之哨兵机制
哨兵机制 在前面讲的master/slave模式,在一个典型的一主多从的系统中,slave在整个体系中起到了数据冗余备份和读写分离的作用.当master遇到异常终端后,需要从slave中选举一个新的m ...
- redis高可用(哨兵机制)
redis哨兵机制:redis的哨兵系统用于管理多个reids服务器,该系统主要有三个作用: 监控:哨兵 会不断地检查你的主服务(Master)和从服务器(Slave)是否运作正常. 提醒:当被监控的 ...
- Redis高可用方案哨兵机制------ 配置文件sentinel.conf详解
Redis的哨兵机制是官方推荐的一种高可用(HA)方案,我们在使用Redis的主从结构时,如果主节点挂掉,这时是不能自动进行主备切换和通知客户端主节点下线的. Redis-Sentinel机制主要用三 ...
- Java基础篇(JVM)——类加载机制
这是Java基础篇(JVM)的第二篇文章,紧接着上一篇字节码详解,这篇我们来详解Java的类加载机制,也就是如何把字节码代表的类信息加载进入内存中. 我们知道,不管是根据类新建对象,还是直接使用类变量 ...
- Redis基础篇(三)持久化:AOF日志
Redis是内存数据库,但是一旦服务器宕机,内存中的数据将会全部丢失. 最简单的恢复方式是从后端数据库恢复,但这种方式有两个问题: 频繁访问数据库,会给数据库带来巨大的压力: 从数据库中读取相比从Re ...
- Redis基础篇(八)数据分片
现在有一个场景:要用Redis保存5000万个键值对,每个键值对大约是512B,要怎么部署Redis服务呢? 第一个方案,也是最容易想到的,需要保存5000万个键值对,每个键值对约为512B,一共需要 ...
- Lua 学习之基础篇七<Lua Module,Package介绍>
Lua 之Module介绍 包管理库提供了从 Lua 中加载模块的基础库. 只有一个导出函数直接放在全局环境中: [require]. 所有其它的部分都导出在表 package 中. require ...
- redis基础篇
1.redis常见的数据结构 redis是一种以键值对存储的高性能内存数据库,有五种常用的数据类型,string,list,hash,set,zset. 2.redis的过期时间 redis中的key ...
随机推荐
- moviepy音视频剪辑:视频剪辑基类VideoClip的属性及方法详解
☞ ░ 前往老猿Python博文目录 ░ 一.概述 在<moviepy音视频剪辑:moviepy中的剪辑基类Clip详解>和<moviepy音视频剪辑:moviepy中的剪辑基类Cl ...
- 第7.16节 案例详解:Python中classmethod定义的类方法
第7.16节 案例详解:Python中classmethod定义的类方法 上节介绍了类方法定义的语法以及各种使用的场景,本节结合上节的知识具体举例说明相关内容. 一. 案例说明 本节定义的一个 ...
- PyQt(Python+Qt)学习随笔:键盘焦点和逻辑焦点(Logic Focus与Keyboard Focus )
老猿Python博文目录 专栏:使用PyQt开发图形界面Python应用 老猿Python博客地址 Qt中的焦点有键盘焦点和逻辑焦点(Logic Focus与Keyboard Focus )的区分,键 ...
- PyQt(Python+Qt)学习随笔:布局控件layoutStretch属性
在Qt Designer中布局控件有4个,分别是Vertical Layout(垂直布局).Horizontal Layout(水平布局).Grid Layout(网格布局).Form Layout( ...
- js中的(function(){})()立即执行
( function(){-} )() 和 ( function (){-} () ) 是两种javascript立即执行函数的常见写法,要理解立即执行函数,需要先理解一些函数的基本概念. 函数声明. ...
- 学习笔记:插头DP
基于连通性的状压DP问题. 一般是给你一个网格,有一些连通性的限制. 例题 插头DP模板 链接 题意:网格图,去掉一些点,求哈密顿回路方案数. 一般按格递推(从上到下,从左到右). 每个格子要从四个方 ...
- SNOI2020 部分题解
D1T1 画图可以发现,多了一条边过后的图是串并联图.(暂时不确定) 然后我们考虑把问题变成,若生成树包含一条边\(e\),则使生成树权值乘上\(a_e\),否则乘上\(b_e\),求最终的生成树权值 ...
- NOI Online #2 提高组 游记
没 NOI Online 1 挂的惨就来写游记吧,不知道为啥 NOI Online 1 民间数据测得 60 分的 T1 最后爆零了... 昏昏沉沉的醒来,吃了早饭,等到 \(8:30\) 进入比赛网页 ...
- MySQL5.7 主主复制配置
MySQL 5.7 主主复制配置 一.简介: MySQL主主复制其实就是两个MySQL主从复制组合到一起,接着我的上一篇博客<centos 7 配置 mysql 5.7 主从复制>配置即可 ...
- 【PY从0到1】第一节 安装与界面介绍
本系列是介绍如何用Python进行股票量化交易的课程. 课程内容以记录Python零基础学员从最简单的Python下载及安装开始,到最后能熟练运用Python进行量化交易的专业人员的成长历程.旨在打造 ...