【基础篇】哨兵机制:主库挂了,如何不间断服务?

server/2024/10/15 21:37:50/

背景

上篇文章中,我们学习了主从库集群模式。在这个模式下,如果从库发生故障了,客户端可以继续向主库或其他从库发送请求,进行相关的操作,但是如果主库发生故障了,那就直接会影响到从库的同步,因为从库没有相应的主库可以进行数据复制操作了。

而且,如果客户端发送的都是读操作请求,那还可以由从库继续提供服务,这在纯读的业务场景下还能被接受。但是,一旦有写操作请求了,按照主从库模式下的读写分离要求,需要由主库来完成写操作。此时,也没有实例可以来服务客户端的写操作请求了。

无论是写服务中断,还是从库无法进行数据同步,都是不能接受的。所以,如果主库挂了,我们就需要运行一个新主库,比如说把一个从库切换为主库,把它当成主库。这就涉及到三个问题:

  1. 主库真的挂了吗?
  2. 该选择哪个从库作为主库?
  3. 怎么把新主库的相关信息通知给从库和客户端呢?

这就要提到哨兵机制了。在 Redis 主从集群中,哨兵机制是实现主从库自动切换的关键机制,它有效地解决了主从复制模式下故障转移的这三个问题。

哨兵机制的基本流程

哨兵其实就是一个运行在特殊模式下的 Redis 进程,主从库实例运行的同时,它也在运行。哨兵主要负责的就是三个任务:监控、选主(选择主库)和通知。

我们先看监控。监控是指哨兵进程在运行时,周期性地给所有的主从库发送 PING 命令,检测它们是否仍然在线运行。如果从库没有在规定时间内响应哨兵的 PING 命令,哨兵就会把它标记为“下线状态”;同样,如果主库也没有在规定时间内响应哨兵的 PING 命令,哨兵就会判定主库下线,然后开始自动切换主库的流程。

这个流程首先是执行哨兵的第二个任务,选主。主库挂了以后,哨兵就需要从很多个从库里,按照一定的规则选择一个从库实例,把它作为新的主库。这一步完成后,现在的集群里就有了新主库。

然后,哨兵会执行最后一个任务:通知。在执行通知任务时,哨兵会把新主库的连接信息发给其他从库,让它们执行 replicaof 命令,和新主库建立连接,并进行数据复制。同时,哨兵会把新主库的连接信息通知给客户端,让它们把请求操作发到新主库上。

在这三个任务中,通知任务相对来说比较简单,哨兵只需要把新主库信息发给从库和客户端,让它们和新主库建立连接就行,并不涉及决策的逻辑。但是,在监控和选主这两个任务中,哨兵需要做出两个决策:

  • 在监控任务中,哨兵需要判断主库是否处于下线状态;
  • 在选主任务中,哨兵也要决定选择哪个从库实例作为主库。

主观下线和客观下线

哨兵进程会使用 PING 命令检测它自己和主、从库的网络连接情况,用来判断实例的状态。 如果哨兵发现主库或从库对 PING 命令的响应超时了,那么,哨兵就会先把它标记为“主观下线”。

如果检测的是从库,那么,哨兵简单地把它标记为“主观下线”就行了,因为从库的下线影响一般不太大,集群的对外服务不会间断。

但是,如果检测的是主库,那么,哨兵还不能简单地把它标记为“主观下线”,开启主从切换。因为很有可能存在这么一个情况:那就是哨兵误判了,其实主库并没有故障。可是,一旦启动了主从切换,后续的选主和通知操作都会带来额外的计算和通信开销。

通常会采用多实例组成的集群模式进行部署,这也被称为哨兵集群。 引入多个哨兵实例一起来判断,就可以避免单个哨兵因为自身网络状况不好,而误判主库下线的情况。同时,多个哨兵的网络同时不稳定的概率较小,由它们一起做决策,误判率也能降低。

在判断主库是否下线时,不能由一个哨兵说了算,只有大多数的哨兵实例,都判断主库已经“主观下线”了,主库才会被标记为“客观下线”,这个叫法也是表明主库下线成为一个客观事实了。这个判断原则就是:少数服从多数。同时,这会进一步触发哨兵开始主从切换流程。

好了,到这里,你可以看到,借助于多个哨兵实例的共同判断机制,我们就可以更准确地判断出主库是否处于下线状态。如果主库的确下线了,哨兵就要开始下一个决策过程了,即从许多从库中,选出一个从库来做新主库。

如何选定新主库?

一般来说,我把哨兵选择新主库的过程称为“筛选 + 打分”。简单来说,我们在多个从库中,先按照一定的筛选条件,把不符合条件的从库去掉。然后,我们再按照一定的规则,给剩下的从库逐个打分,将得分最高的从库选为新主库,如下图所示:
在这里插入图片描述
首先来看筛选的条件。

一般情况下,我们肯定要先保证所选的从库仍然在线运行。不过,在选主时从库正常在线,这只能表示从库的现状良好,并不代表它就是最适合做主库的。

设想一下,如果在选主时,一个从库正常运行,我们把它选为新主库开始使用了。可是,很快它的网络出了故障,此时,我们就得重新选主了。这显然不是我们期望的结果。

所以,在选主时,除了要检查从库的当前在线状态,还要判断它之前的网络连接状态。 如果从库总是和主库断连,而且断连次数超出了一定的阈值,我们就有理由相信,这个从库的网络状况并不是太好,就可以把这个从库筛掉了。

具体怎么判断呢?你使用配置项 down-after-milliseconds * 10。其中,down-after-milliseconds 是我们认定主从库断连的最大连接超时时间。如果在 down-after-milliseconds 毫秒内,主从节点都没有通过网络联系上,我们就可以认为主从节点断连了。如果发生断连的次数超过了 10 次,就说明这个从库的网络状况不好,不适合作为新主库。

好了,这样我们就过滤掉了不适合做主库的从库,完成了筛选工作。

接下来就要给剩余的从库打分了。我们可以分别按照三个规则依次进行三轮打分,这三个规则分别是从库优先级、从库复制进度以及从库 ID 号。只要在某一轮中,有从库得分最高,那么它就是主库了,选主过程到此结束。如果没有出现得分最高的从库,那么就继续进行下一轮。

第一轮:优先级最高的从库得分高。

用户可以通过 slave-priority 配置项,给不同的从库设置不同优先级。

第二轮:和旧主库同步程度最接近的从库得分高。

这个进度就是上篇文章中的,slave_repl_offset 的大小。

第三轮:ID 号小的从库得分高。

每个实例都会有一个 ID,这个 ID 就类似于这里的从库的编号。目前,Redis 在选主库时,有一个默认的规定:在优先级和复制进度都相同的情况下,ID 号最小的从库得分最高,会被选为新主库。

到这里,新主库就被选出来了,“选主”这个过程就完成了。

我们再回顾下这个流程。首先,哨兵会按照在线状态、网络状态,筛选过滤掉一部分不符合要求的从库,然后,依次按照优先级、复制进度、ID 号大小再对剩余的从库进行打分,只要有得分最高的从库出现,就把它选为新主库。

小结

这篇文章,我们一起学习了哨兵机制,它是实现 Redis 不间断服务的重要保证。具体来说,主从集群的数据同步,是数据可靠的基础保证;而在主库发生故障时,自动的主从切换是服务不间断的关键支撑。

Redis 的哨兵机制自动完成了以下三大功能,从而实现了主从库的自动切换,可以降低 Redis 集群的运维开销:

  • 监控主库运行状态,并判断主库是否客观下线;
  • 在主库客观下线后,选取新主库;
  • 选出新主库后,通知从库和客户端。

为了降低误判率,在实际应用时,哨兵机制通常采用多实例的方式进行部署,多个哨兵实例通过“少数服从多数”的原则,来判断主库是否客观下线。

每课一问

按照惯例,我给你提个小问题。这节课,我提到,通过哨兵机制,可以实现主从库的自动切换,这是实现服务不间断的关键支撑,同时,我也提到了主从库切换是需要一定时间的。所以,请你考虑下,在这个切换过程中,客户端能否正常地进行请求操作呢?如果想要应用程序不感知服务的中断,还需要哨兵或需要客户端再做些什么吗?

  1. 主从集群一般是采用读写分离模式,当主库故障后,客户端仍然可以把读请求发送给从库,让从库服务。但是,对于写请求操作,客户端就无法执行了。
  2. 一方面,客户端需要能缓存应用发送的写请求。只要不是同步写操作(Redis 应用场景一般也没有同步写),写请求通常不会在应用程序的关键路径上,所以,客户端缓存写请求后,给应用程序返回一个确认就行。
  3. 另一方面,主从切换完成后,客户端要能和新主库重新建立连接,哨兵需要提供订阅频道,让客户端能够订阅到新主库的信息。同时,客户端也需要能主动和哨兵通信,询问新主库的信息。

http://www.ppmy.cn/server/132384.html

相关文章

企业在隔离网环境下如何进行安全又稳定的跨网文件交换?

在数字化时代,企业的数据流通如同血液一般重要。然而,当企业内部实施了隔离网环境,跨网文件交换就成了一个棘手的问题。今天我们将探讨在隔离网环境下,企业面临的跨网文件交换挑战,以及如何通过合规的跨网文件交换系统…

2015年-2017年 计算机技术专业 程序设计题(算法题)实战_c语言程序设计数据结构程序设计分析

文章目录 20151.C语言算法设计部分2.数据结构算法设计部分 20161.C语言算法设计部分2.数据结构算法设计部分 2017年1. C语言算法设计部分2.数据结构算法设计部分 2015 1.C语言算法设计部分 int total(int n) {if(n1) return 1;return total(n-1)n1; } //主函数测试代码已省略…

Java 日志打印

使用日志打印: private static Logger log LoggerFactory.getLogger(DeptController.class);RequestMapping("/depts")public Result list() { // System.out.println("查询全部部门数据");log.info("查询全部部门数据");ret…

AGI|如何构建一个RAG应用?入门新手攻略!

目录 一、概述 二、过程概述 三、如何优化提问? 四、路由和高级查询 五、丰富索引结构 六、重排序上下文 七、总结 一、概述 Retrieval Augmented Generation RAG 检索增强的内容生成。 从字面上来看检索只是一种手段途径,在人工智能领域中存在多种…

【30天玩转python】最后复习与总结

最后复习与总结 复习要点 在过去的 30 天中,我们从基础到高阶全面学习了 Python 编程,涵盖了各种实用的编程技巧与概念,以下是对本次学习的主要复习点: 1. Python 基础 Python 简介与安装:我们首先了解了 Python 的…

git更加详细和灵活的提交过程,附带如何配置. gitignore来忽略部分文件的提交。

本套流程可以控制提交的代码是哪些,比直接使用git add . 更灵活,比如在项目中,一些文件不能通过.gitignore进行尽职提交,那么就需要使用本方法来手动控制是否提交,缺点就是相对麻烦一些。 git status//查看从当前工作…

什么是人工智能 (AI)?

什么是人工智能? 人工智能(AI)是致力于解决通常与人类智能相关联的认知性问题的计算机科学领域,这些问题包括学习、创造和图像识别等。现代组织从各种来源收集大量数据,例如智能传感器、人工生成的内容、监控工具和系统…

《超详细Redisson实战用法· 看这一篇就可以了》

📢 大家好,我是 【战神刘玉栋】,有10多年的研发经验,致力于前后端技术栈的知识沉淀和传播。 💗 🌻 CSDN入驻不久,希望大家多多支持,后续会继续提升文章质量,绝不滥竽充数…