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 ...
随机推荐
- 利用Python特殊变量__dict__快速实现__repr__的一种方法
在<第8.15节 Python重写自定义类的__repr__方法>.<Python中repr(变量)和str(变量)的返回值有什么区别和联系>.<第8.13节 Pytho ...
- Java数据结构(十五)—— 多路查找树
多路查找树 二叉树和B树 二叉树的问题分析 二叉树操作效率高 二叉树需要加载到内存,若二叉树的节点多存在如下问题: 问题1:构建二叉树时,需多次进行I/O操作,对与速度有影响 问题2:节点海量造成二叉 ...
- (四)一个bug的生命周期
Bug的属性 Bug重现环境 这个应该是我们重现BUG的一个前提,如果没有这个前提,我们可能会无法重现问题,或者根本就无从下手. • 操作系统 这个是一般软件运行的一大前提,基本上所有的软件都依赖于操 ...
- ARC109D - L
平面上一开始有三个点\((0,0),(0,1),(1,0)\)形成成L形(点连续),每次操作可以将一个点改变位置,使得得到的仍然是L形.给出终止L形的位置,问移动的最小步数. \(|x|,|y|\le ...
- 转载:c# 获取CPU温度(非WMI,直接读取硬件)
c#获取cpu温度 很早一个项目做远控,所以需要用到获取cpu温度,但是就是不知从何下手,无意中发现了Open Hardware Monitor,令我的项目成功完成 亲测20台清装xp sp2的机器, ...
- Spring AOP的理解(通俗易懂)。
转载 原文链接:http://www.verydemo.com/demo_c143_i20837.html 这种在运行时,动态地将代码切入到类的指定方法.指定位置上的编程思想就是面向切面的编程. 1. ...
- js v-if 判断多个属性 in
js v-if 判断 <div v-if="suborder.approve_user==user_id || suborder.approve_userrole_id in rol ...
- 推荐系统实践 0x0f AutoRec
从这一篇开始,我们开始学习深度学习推荐模型,与传统的机器学习相比,深度学习模型的表达能力更强,并且更能够挖掘出数据中潜藏的模式.另外.深度学习模型结构也非常灵活,能够根据业务场景和数据结构进行调整.还 ...
- Java JVM——2.类加载器子系统
概述 类加载器子系统在Java JVM中的位置 类加载器子系统的具体实现 类加载器子系统的作用 ① 负责从文件系统或者网络中加载.class文件,Class 文件在文件开头有特定的文件标识. ② Cl ...
- Peomise
什么是promise 简单回答: 一种异步的解决方案 回顾一下什么是异步 事件 / setTimeout 异步执行的时机 同步->异步微任务->GUI渲染->异步宏任务 #为 ...