Redis高可用全景一览

news2024/10/5 18:29:20

前言

前几天我在知乎看到一个问题:如何建立自己的知识体系和观点?[1]

如何建立自己的知识体系和观点?

在一篇高赞回答中讲述了建立“外脑”是关键,文章观点认为:大脑是用来思考的,不是用来记忆的。

查理芒格

我很认同这样的看法,我的账号名为“杨同学technotes”,technotes[2] 源于我最近几年总结的 github 项目,意为“技术笔记”,这便是我的“外脑”。我将一直往里面填充东西,不断优化内容,欢迎关注。

  • [1] https://www.zhihu.com/question/52782284/answer/1857387360
  • [2] https://www.dbses.cn/technotes

本文来自我的 technotes Redis篇。

正文

对于一项技术的学习,我们要对这项技术有一个全局观,下面是一张 Redis 全景图,我觉得画得非常全面。

图源:极客时间《Redis核心技术与实战》-蒋德均

今天我们主要关注 Redis 的高可用主线。Redis 的高可用性,具体来说,有两方面含义:一是服务少中断,二是数据少丢失。

为了保证服务少中断,通常的做法就是冗余,增加服务的副本,但是当副本多了以后,如何保证副本的数据一致就成了问题。

一、主从库模式

在这方面,Redis 提供了主从库模式,主从库之间采用的是读写分离的方式:对于读操作请求,主从库都可以接收;对于写操作,首先到主库执行,然后,主库将写操作同步给从库。

Redis读写分离

那么,主从库同步是如何完成的呢?主库数据是一次性传给从库,还是分批同步?要是主从库间的网络断连了,数据还能保持一致吗?

1.1 数据同步的实现细节

当我们启动多个 Redis 实例的时候,它们相互之间就可以通过 replicaof(Redis 5.0 之前使用 slaveof)命令形成主库和从库的关系。

例如,现在有实例 1(ip:172.16.19.3)和实例 2(ip:172.16.19.5),我们在实例 2 上执行以下这个命令后,实例 2 就变成了实例 1 的从库,并从实例 1 上复制数据:

replicaof 172.16.19.3 6379

之后会按照三个阶段完成数据的第一次同步。

第一阶段:主从库间建立连接、协商同步的过程,主要是为全量复制做准备。具体来说,从库给主库发送 psync 命令,表示要进行数据同步,主库根据这个命令的参数来启动复制。psync 命令包含了主库的 runID 和复制进度 offset 两个参数。runID,是每个 Redis 实例启动时都会自动生成的一个随机 ID,用来唯一标记这个实例。当从库和主库第一次复制时,因为不知道主库的 runID,所以将 runID 设为“?”。offset,此时设为 -1,表示第一次复制。

主库收到 psync 命令后,会用 FULLRESYNC 响应命令带上两个参数:主库 runID 和主库目前的复制进度 offset(这个offset是当前最新的值),返回给从库。从库收到响应后,会记录下这两个参数。

第二阶段:主库将所有数据同步给从库。具体来说,主库执行 bgsave 命令,生成 RDB 文件,接着将文件发给从库。从库接收到 RDB 文件后,会先清空当前数据库,然后加载 RDB 文件。

为什么要先清空当前数据库呢?这是因为从库在通过 replicaof 命令开始和主库同步前,可能保存了其他数据。为了避免之前数据的影响,从库需要先把当前数据库清空。

在主库将数据同步给从库的过程中,主库不会被阻塞,仍然可以正常接收请求。否则,Redis 的服务就被中断了。但是,这些请求中的写操作并没有记录到刚刚生成的 RDB 文件中。为了保证主从库的数据一致性,主库会在内存中用专门的 replication buffer,记录 RDB 文件生成后收到的所有写操作。

第三阶段:当主库完成 RDB 文件发送后,就会把此时 replication buffer 中的修改操作发给从库,从库再重新执行这些操作。

主从复制整个过程示意图如下所示。

主从库第一次同步的三个阶段

这样一来,主从库就实现同步了。不可忽视的是,这个过程中存在着风险点,最常见的就是网络断连或阻塞。如果网络断连,主从库之间就无法进行命令传播了,从库的数据自然也就没办法和主库保持一致了,客户端就可能从从库读到旧数据。

1.2 主从库间网络断了怎么办?

在 Redis 2.8 之前,如果主从库在命令传播时出现了网络闪断,那么,从库就会和主库重新进行一次全量复制,开销非常大。从 Redis 2.8 开始,网络断了之后,主从库会采用增量复制的方式继续同步。只把主从库网络断连期间主库收到的命令,同步给从库。

当主从库断连后,主库会把断连期间收到的写操作命令,写入 replication buffer,同时也会把这些操作命令写入 repl_backlog_buffer 这个缓冲区。repl_backlog_buffer 是一个环形缓冲区,主库会记录自己写到的位置,从库则会记录自己已经读到的位置。

在网络断连阶段,主库可能会收到新的写操作命令,所以,一般来说,主库写到的位置会大于从库读到的位置。当网络恢复后,主库只用把主库写到的位置和从库读到的位置之间的命令操作同步给从库就行。

repl_backlog_buffer示意图

Redis 通过主从库模式,既提高了系统处理请求的吞吐量,也保证了系统的可用性。

如果从库发生故障了,客户端可以继续向主库或其他从库发送请求,进行相关的操作。但是如果主库发生故障了怎么办?此时从库没有相应的主库可以进行数据复制操作了,且一旦有写操作请求,系统也将无法处理。

二、哨兵机制

所以,如果主库挂了,我们就需要运行一个新主库,比如说把一个从库切换为主库,把它当成主库。在 Redis 主从集群中,哨兵机制是实现主从库自动切换的关键机制。

Redis哨兵机制

2.1 哨兵的职责

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

哨兵的职责

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

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

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

但是你有没有想过,如果有哨兵实例在运行时发生了故障,主从库还能正常切换吗?

2.2 哨兵的高可用

哨兵单点故障问题,Redis 也是通过建立哨兵集群来解决的。那我们再回头看哨兵的职责,在监控主从库是否下线时,如果出现了哨兵内部的意见不统一怎么办?比如说有 3 个哨兵,其中一个哨兵认为主库下线了,而另外 2 个却认为主库是正常的,这时该听谁的呢?

这就好比我们团队内部出现了意见分歧,那最好的解决办法就是民主投票了,采用“少数服从多数的原则”。哨兵集群内部也一样,在网络拥塞的情况下,有个别哨兵与主库的 PING 命令失败,这时哨兵就认为该主库故障了,然而实际并没有。这时就要采用“民主”的办法,大多数哨兵认为主库故障,才会进行下一步的选主。

哨兵的实例数应该是 2N+1 的单数,这样才不致于出现观点对立的情况,通常我们至少会配置 3 个哨兵实例。

那选主同样需要考虑一个问题:哨兵这么多,该由哪个执行主从切换?

此时,这个哨兵就可以再给其他哨兵发送命令,表明希望由自己来执行主从切换,并让所有其他哨兵进行投票。这个投票过程称为“Leader 选举”。因为最终执行主从切换的哨兵称为 Leader,投票过程就是确定 Leader。

到这里,我们就大致理清了 Redis 保证服务少中断所采取的一系列方案了。那 Redis 是如何保证数据少丢失的呢?

三、AOF和RDB

了解 MySQL 的同学可能听说过,MySQL 是具有 Crasf-Safe 的能力的,这归功于数据库的写前日志(Write Ahead Log, WAL) Redo Log。同样,Redis 也提供了 AOF 日志。

3.1 主库宕机了,如何避免数据丢失?

AOF 里记录的是 Redis 收到的每一条命令,这些命令是以文本形式保存的。我们以 Redis 收到“set testkey testvalue”命令后记录的日志为例,看看 AOF 日志的内容。其中,“ *3 ”表示当前命令有三个部分,每部分都是由“$+数字”开头,后面紧跟着具体的命令、键或值。这里,“数字”表示这部分中的命令、键或值一共有多少字节。例如,“$3 set”表示这部分有 3 个字节,也就是“set”命令。

AOF日志内容

但是,因为记录的是操作命令,而不是实际的数据,所以,用 AOF 方法进行故障恢复的时候,需要逐一把操作日志都执行一遍。如果操作日志非常多,Redis 就会恢复得很缓慢,影响到正常使用。

因此,Redis 提供了另一种数据持久化方法:内存快照 RDB。和 AOF 相比,RDB 记录的是某一时刻的数据,并不是操作,所以,在做数据恢复时,我们可以直接把 RDB 文件读入内存,很快地完成恢复。

对于快照来说,系统多久执行一次快照直接影响数据丢失的多少。如下图所示,我们先在 T0 时刻做了一次快照,然后又在 T0+t 时刻做了一次快照,在这期间,数据块 5 和 9 被修改了。如果在 t 这段时间内,机器宕机了,那么,只能按照 T0 时刻的快照进行恢复。此时,数据块 5 和 9 的修改值因为没有快照记录,就无法恢复了。

RDB数据丢失

所以,要想尽可能恢复数据,t 值就要尽可能小。那么,t 值可以小到什么程度呢,比如说是不是可以每秒做一次快照?

3.2 宕机后,如何快速恢复数据?

Redis 4.0 中提出了一个混合使用 AOF 和 RDB 的方法。简单来说,内存快照以一定的频率执行,在两次快照之间,使用 AOF 日志记录这期间的所有命令操作。

这样一来,快照不用很频繁地执行。而且,AOF 日志也只用记录两次快照间的操作,也就是说,不需要记录所有操作了,因此,就不会出现文件过大的情况了,也可以避免重写开销。

RDB与AOF混合使用

这个方法既能享受到 RDB 文件快速恢复的好处,又能享受到 AOF 只记录操作命令的简单优势。

小结

我来总结一下本文的内容。Redis 系统的高可用,具体可以通过两个方面来理解:一是服务少中断,二是数据少丢失。我整理的知识消化链路如下。

服务少中断 -> 多副本 -> 主从库模式保证数据一致及从库的高可用 -> 哨兵保证主库的高可用 -> 哨兵集群保证哨兵高可用。
数据少丢失 -> AOF日志 -> AOF恢复数据较慢 -> RDB内存快照 -> 执行快照间隔不宜过短 -> AOF+RDB

关于哨兵机制的更多实现细节,我会在后面的内容里继续更新,敬请关注。公众号「杨同学technotes」,欢迎技术交流。

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

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

相关文章

电脑怎么滚动截图的方法

电脑截图常见的有矩形截图、任意形状截图、全屏幕截图、窗口截图等等,那你知道怎么在电脑上滚动截图吗?有时候可能会需要用到滚动截长图,但是很多 用户都不清楚怎么操作,下面小编就来教教大家电脑怎么滚动截图的方法(除…

云存储--2

那么,根据我们上一版块的延续,我们来讲讲实际在linux中需要如何进行存储方面的一个操作吧。 那么我使用的是RHEL9.1 红帽作为在linux领域具有绝对的话语权和强大的市场,所以使用该系统还是有点原因哒~ 那么可能会有同学有疑问:欸&…

多目标遗传算法NSGAII求解环境经济调度(Python代码实现)

目录 1 电力系统环境经济调度数学模型 2 算例——IEEE10节点 2.1 数据​ 2.2 Python代码学习 3 一点拓展知识 1 电力系统环境经济调度数学模型 2 算例——IEEE10节点 2.1 数据 我弄成一个表格,方便编程读写: 2.2 Python代码学习 多目标遗传算法N…

【Flutter 组件】002-基础组件:文本与样式

【Flutter 组件】002-基础组件:文本与样式 文章目录【Flutter 组件】002-基础组件:文本与样式一、Text1、概述2、属性列表3、构造方法4、示例代码演示运行结果二、TextStyle1、概述2、属性列表3、构造方法4、示例代码示例运行结果三、TextSpan1、概述2、…

数字图像处理(入门篇)十 边缘检测

目录 一 边缘检测算子 1 Roberts算子 2 Sobel算子 3 Prewitt算子 二 实践 (1)代码 (2)结果图 边缘检测是计算机视觉中的基本问题,边缘检测的难点就在于如何又快又准确地提取图像的边缘信息。 边缘检测的基本方法…

流媒体分析之webrtc之rtcp

TCP作为RTP控制协议,对于弱网下音视频质量和会话控制具有重要的作用。 1. RTCP Header V:RTCP的版本号,一定等于2; P:如果设置,填充位表示数据包包含末尾的附加填充八位字节,不属于控制信息&am…

基于jsp+mysql+ssm影视爱好者论坛交流系统-计算机毕业设计

项目介绍 设计一个电影学习交流社区,使对电影的学生可以方便的进行交流。同时,通过此课题使学生熟悉网站搭建流程和方法。 意义:此课题实现后,可以为喜欢电影的学生提供一个交流学习的平台,提高学生学习兴趣。同时&am…

想提前躺平的程序员,这10个网站收好了!

我们的口号是:搞钱!搞钱!再搞钱!程序员想兼职但是不知道该上哪找? 为大家整理了7个程序员最常用的接私活平台,希望对你有帮助!记得点赞收藏,先码后看!1、程序员客栈 程序…

基于jsp+mysql+ssm游戏爱好者论坛交流设计-计算机毕业设计

项目介绍 本论坛是一个面向爱好游戏的玩家提供一个交流分享游戏攻略、视频、图片以及娱乐互动,让游戏玩家展示自己最真实的心声!论坛提供注册、登陆、发帖、回复、搜索等功能。用户可以利用论坛进行网上约伴、分享装备属性及其获得方法,进行账号交易等,…

5 - 线程池 Java内置的线程池 - 异步计算结果(Future)

前面介绍 ExecutorService 线程池接口的时候,其中,提交任务的方法 submit() 的返回值就是Future接口类型的。 我们刚刚在学习java内置线程池使用时,没有考虑线程计算的结果,但开发中,我们有时需要利用线程进行一些计算…

2022年牙科医疗行业研究报告

第一章 行业概况 1.1 牙科医疗概念及现状 牙科医疗行业是指以牙科医疗消费为基础,集合了牙科医疗服务、职业牙医教育培训、牙科医疗器材研究开发生产、市场策划、宣传、投资、经营、管理等于一体的医疗产业链。由于牙科疾病的特点,牙科医疗产业在具有一…

iOS扫码一图多码原生处理AVCaptureSession

文章目录前言正文1.定位二维码的位置2.扫码、解析总结前言 业务中一直有扫码的需求,这次说需要扫多个码(详细一点是一图多码),有点东西的。 第一点:怎么做:拿到手第一反应是有没有什么库可以直接调用的&am…

VSCode远程连接免密登录

配置了VSCode远程连接服务器,但每次打开project都需要重新输入密码,比较麻烦,所以下面就介绍一下如何免密码登入 在上一篇blog里面配置好VSCode远程连接服务器之后按照如下操作。 步骤如下: 在windows端: 1、winR打…

softmax原理性质解析并python实现

Softmax原理 Softmax函数用于将分类结果归一化,形成一个概率分布。作用类似于二分类中的Sigmoid函数。 对于一个k维向量z,我们想把这个结果转换为一个k个类别的概率分布p(z)。softmax可以用于实现上述结果,具体计算公式为: 对于k…

【数集项目之 MCDF】(一) 控制寄存器 control_register

写在前面 本项目为MCDF数据整形器设计,所有的参考代码见我的github https://github.com/SuperiorLQF/verilog_ALL/tree/master/MCDF 其中设计的参考文档见github文件中的MCDF修订版.docx文件。选择的工具链是Vscode & iverilog & gtkwave,相关工…

前端框架 Nuxt3 Vue3 SSR 总结

目录 一、Nuxt3安装 二、路由 1、普通路由 2、动态路由 3、获取路由参数 4、路由跳转标签 5、路由跳转api 三、静态资源 四、常用标签 1、title标签、useHead的API 五、公共模板布局 1、默认布局 2、自定义公共模板 3、动态自定义布局 六、插件 七、中间件 …

【QString 函数学习篇】

【QString 函数学习篇】【1】UI设计布局【2】QChar | setAlignment |【3】sprintf | asprintf | setNum | number |【4】toInt | toUpper [十进制->十六进制 | 十进制->二进制]【5】clear | append【6】二进制->十六进制 | 二进制->十进制【7】prepend【8】strimme…

[附源码]Python计算机毕业设计SSM基于的餐厅管理系统(程序+LW)

项目运行 环境配置: Jdk1.8 Tomcat7.0 Mysql HBuilderX(Webstorm也行) Eclispe(IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持)。 项目技术: SSM mybatis Maven Vue 等等组成,B/S模式 M…

(十二)Vue之列表渲染

文章目录基本列表遍历数组遍历对象遍历字符串遍历指定次数key的原理虚拟DOM中key的作用用index作为key可能会引发的问题如何选择keyVue学习目录 上一篇:(十一)Vue之条件渲染 基本列表 在vue里基本的列表渲染可以使用v-for指令 v-for指令: …

Reactor手册

Flux Flux 是一个发出0-N个元素组成的异步序列的Publisher,可以被onComplete信号或者onError信号所终止。 Flux.just("Hello", "World").subscribe(System.out::println);// fromArray(),fromIterable(),fromStream()Flux.fromArra…