您当前的位置:首页 > 电脑百科 > 数据库 > Redis

Redis高可用全景一览

时间:2022-12-11 14:13:47  来源:今日头条  作者:杨同学technotes

正文

对于一项技术的学习,我们要对这项技术有一个全局观,下面是一张 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」,欢迎技术交流。



Tags:Redis   点击:()  评论:()
声明:本站部分内容及图片来自互联网,转载是出于传递更多信息之目的,内容观点仅代表作者本人,如有任何标注错误或版权侵犯请与我们联系(Email:2595517585@qq.com),我们将及时更正、删除,谢谢。
▌相关推荐
正文对于一项技术的学习,我们要对这项技术有一个全局观,下面是一张 Redis 全景图,我觉得画得非常全面。图源:极客时间《Redis核心技术与实战》-蒋德均今天我们主要关注 Redis 的...【详细内容】
2022-12-11  Tags: Redis  点击:(0)  评论:(0)  加入收藏
一、自动注入没有添加泛型问题自定义RedisTemplate<String,Object>后,在使用时,需要在自动注入的RedisTemplate中添加泛型为RedisTemplate<String,Object>,否则会报错:com.fast...【详细内容】
2022-11-01  Tags: Redis  点击:(66)  评论:(0)  加入收藏
Redis作为内存数据库,拥有非常高的性能,单个实例的QPS能够达到10W左右。但我们在使用Redis时,经常时不时会出现访问延迟很大的情况,如果你不知道Redis的内部实现原理,在排查问题时就会一头雾水。...【详细内容】
2022-11-01  Tags: Redis  点击:(31)  评论:(0)  加入收藏
HyperLogLog,可能很多人对Redis这个功能都很陌生,在日常开发中也很少用到它,或者用了它也没有深入的了解过,下面我们将详细介绍。HyperLogLog简称HLL,它是LogLog算法的升级版,其功...【详细内容】
2022-10-26  Tags: Redis  点击:(34)  评论:(0)  加入收藏
下载地址:下载界面:下载好之后进行安装安装界面下一步安装路径的改动默认下一步继续下一步安装点击完成这是我们的安装目录最简单的启动方式是直接双击redis-server.exe如果要...【详细内容】
2022-10-10  Tags: Redis  点击:(38)  评论:(0)  加入收藏
很难大规模操作有状态的分布式系统,Redis 也不例外。托管数据库通过承担大部分繁重工作使生活变得更轻松。但是您仍然需要一个健全的架构并在服务器(Redis)和客户端(应用程序)上...【详细内容】
2022-10-08  Tags: Redis  点击:(40)  评论:(0)  加入收藏
Apache Kafka 已成为大多数技术栈中的主流组件。使用 Kafka 的好处包括确保事件中的因果顺序,同时保持并行性,通过在服务器之间快速复制分区来恢复故障,等等。 然而,运行 Kafka...【详细内容】
2022-10-04  Tags: Redis  点击:(70)  评论:(0)  加入收藏
一、背景公司基于业务发展以及战略部署,需要实现在多个数据中心单元化部署,一方面可以实现多数据中心容灾,另外可以提升用户请求访问速度。需要保证多数据中心容灾或者实现用户...【详细内容】
2022-09-28  Tags: Redis  点击:(68)  评论:(0)  加入收藏
一、RedisInsight 简介RedisInsight 是一个高颜值,直观高效的 Redis GUI 管理工具,它可以对 Redis 的内存、连接数、命中率以及正常运行时间进行监控,并且可以在界面上使用 CL...【详细内容】
2022-09-18  Tags: Redis  点击:(136)  评论:(0)  加入收藏
一、Redis为什么那么快 QPS达到10万/秒 用C语言实现 基于内存 单线程,不用线程上下文切换及加锁二、redis数据类型 String,常见的缓存,存储登录session等 hash,存储对象,单独修...【详细内容】
2022-09-16  Tags: Redis  点击:(94)  评论:(0)  加入收藏
▌简易百科推荐
正文对于一项技术的学习,我们要对这项技术有一个全局观,下面是一张 Redis 全景图,我觉得画得非常全面。图源:极客时间《Redis核心技术与实战》-蒋德均今天我们主要关注 Redis 的...【详细内容】
2022-12-11  杨同学technotes  今日头条  Tags:Redis   点击:(0)  评论:(0)  加入收藏
Redis作为内存数据库,拥有非常高的性能,单个实例的QPS能够达到10W左右。但我们在使用Redis时,经常时不时会出现访问延迟很大的情况,如果你不知道Redis的内部实现原理,在排查问题时就会一头雾水。...【详细内容】
2022-11-01  呆萌小可萘日常    Tags:Redis   点击:(31)  评论:(0)  加入收藏
HyperLogLog,可能很多人对Redis这个功能都很陌生,在日常开发中也很少用到它,或者用了它也没有深入的了解过,下面我们将详细介绍。HyperLogLog简称HLL,它是LogLog算法的升级版,其功...【详细内容】
2022-10-26  搬长你好  今日头条  Tags:Redis   点击:(34)  评论:(0)  加入收藏
下载地址:下载界面:下载好之后进行安装安装界面下一步安装路径的改动默认下一步继续下一步安装点击完成这是我们的安装目录最简单的启动方式是直接双击redis-server.exe如果要...【详细内容】
2022-10-10  分享电脑学习  搜狐号  Tags:Redis   点击:(38)  评论:(0)  加入收藏
很难大规模操作有状态的分布式系统,Redis 也不例外。托管数据库通过承担大部分繁重工作使生活变得更轻松。但是您仍然需要一个健全的架构并在服务器(Redis)和客户端(应用程序)上...【详细内容】
2022-10-08  qaseven  网易号  Tags:Redis   点击:(40)  评论:(0)  加入收藏
Apache Kafka 已成为大多数技术栈中的主流组件。使用 Kafka 的好处包括确保事件中的因果顺序,同时保持并行性,通过在服务器之间快速复制分区来恢复故障,等等。 然而,运行 Kafka...【详细内容】
2022-10-04  解道Jdon  今日头条  Tags:Redis   点击:(70)  评论:(0)  加入收藏
一、背景公司基于业务发展以及战略部署,需要实现在多个数据中心单元化部署,一方面可以实现多数据中心容灾,另外可以提升用户请求访问速度。需要保证多数据中心容灾或者实现用户...【详细内容】
2022-09-28  京东云    Tags:Redis   点击:(68)  评论:(0)  加入收藏
一、RedisInsight 简介RedisInsight 是一个高颜值,直观高效的 Redis GUI 管理工具,它可以对 Redis 的内存、连接数、命中率以及正常运行时间进行监控,并且可以在界面上使用 CL...【详细内容】
2022-09-18  Python部落  今日头条  Tags:Redis   点击:(136)  评论:(0)  加入收藏
一、Redis为什么那么快 QPS达到10万/秒 用C语言实现 基于内存 单线程,不用线程上下文切换及加锁二、redis数据类型 String,常见的缓存,存储登录session等 hash,存储对象,单独修...【详细内容】
2022-09-16  互联网资讯看板  网易号  Tags:Redis   点击:(94)  评论:(0)  加入收藏
1、集群原理简介1.1、什么是集群?什么是分区?集群简单的说就是将同一个服务部署在不同的机器上,从而提高服务的横向扩展能力。分区就是将数据分布在多个实例(服务器)上,让每一个实...【详细内容】
2022-09-15  互联共商   网易号  Tags:Redis集群   点击:(87)  评论:(0)  加入收藏
站内最新
站内热门
站内头条