前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >面对集中式缓存实现上的挑战,Redis交出的是何种答卷?聊聊Redis在分布式方面的能力设计

面对集中式缓存实现上的挑战,Redis交出的是何种答卷?聊聊Redis在分布式方面的能力设计

原创
作者头像
是Vzn呀
发布于 2023-01-12 00:50:47
发布于 2023-01-12 00:50:47
4600
举报
文章被收录于专栏:架构悟道架构悟道

大家好,又见面了。


本文是笔者作为掘金技术社区签约作者的身份输出的缓存专栏系列内容,将会通过系列专题,讲清楚缓存的方方面面。如果感兴趣,欢迎关注以获取后续更新。


在本专栏前面的文章中,我们介绍了各种本地缓存框架,也知晓了本地缓存的常见特性与设计理念。在前两篇文章中,我们介绍了集中式缓存 Redis的一些主流特性与典型使用场景。现在我们来对比一下,分布式缓存相比于本地缓存,在实现层面需要关注的点有哪些不同。梳理如下:

维度

本地缓存

集中式缓存

缓存量

受限于单机内存大小,存储数据有限

需要提供给分布式系统里面所有节点共同使用,对于大型系统而言,对集中式缓存的容量诉求非常的大,远超单机内存的容量大小。

可靠性

影响有限,只有本进程使用,不会影响其他进程的可靠性。

作为整个系统扛压屏障,系统内所有节点共同依赖的通用服务,一旦集中式缓存出问题,会影响与其对接的所有业务节点,对系统的影响是致命性的。

承压性

承载单机节点的压力,请求量有限

承载整个分布式集群所有节点的流量,系统内业务分布式节点部署数量越多、业务体量越大,会导致集中缓存要承载的压力就越大,甚至是上不封顶的。

从上述几个维度的对比可以发现,同样是缓存,但集中式缓存所承担的使命是完全不一样的,业务对集中式缓存的存储容量可靠性承压性等方面的诉求也是天壤之别,不可等同视之。以Redis为例:

  • 如何打破redis缓存容量受限于机器单机内存大小的问题?
  • 如何使得redis能够扛住多方过来的请求压力?
  • 如何保证redis不会成为单点故障源?

其实答案很简单,加机器!通过多台机器的叠加使用,达到比单机更优的效果 —— 现在业务系统的集群化部署,也都是采用的这个思路。Redis的分布式之路亦是如此,但相比于常规的业务系统分布式集群化构建更加复杂:

  1. 很多业务实现集群化部署会很简单,因为每个业务进程节点都是无状态的,只需要部署下然后通过负载均衡的方式对外提供请求应答即可。
  2. Redis作为一个集中式缓存数据库,它是有状态的,不仅需要将进程分别部署在多个节点上,还需要将数据也分散存储在各个节点上,同时还得保证整个Redis集群对外是一个统一整体。

所以对于一个集中式缓存的分布式能力构建,必须要额外提供一些机制,来保障数据在各个节点上的安全与一致性,还需要将分散在各个节点上的数据都组成一个逻辑上的整体。

下面,我们以Redis作为集中式缓存的代表,来看下集Redis面对上述各种难题,交出的是怎样的答卷。

Reids部署方式的演进史

单机部署 —— 原始形态,最简单

单机部署只能算是一个开发或测试场景去小范围使用的场景,它与普通本地缓存无二,在可靠性与承压性上无法得到保证。

虽说Redis的性能很高,但俗话也说双拳难敌四手,单机性能再高,也无法抗住大规模集群中所有节点过来的并发请求。此外,单机部署还有个致命点在于其不具备高可用性,系统容易出现单点故障

所以说,稍微正规点的项目,几乎不会有人天真到会用单机模式去部署线上使用。

主从(master-replica)

前面说过单机节点存在诸多问题,很少在生产环境上使用。在实际项目中,有些项目的存储容量要求其实并不是特别的高(比如常规的16G或者32G就已经足够使用),但是需要保证数据的可靠、并且支持大并发量请求,这种情况下,就可以选择主从部署的方式。

对于redis来说,一主两从是比较常见的搭配,如下所示:

主从模式按照读写分离的策略来提升整体的请求处理能力:

  1. 主节点(Master)同时对外提供读和写操作
  2. 从节点(Slave)通过replicate同步的方式,从主节点复制数据,保持自身数据与主节点一致
  3. 从节点只能对外提供读操作

当然,对于读多写少类的操作,为了提升整体读请求的处理能力,可以采用一主多从的方式:

所有的从节点都从主节点进行数据同步,这样会导致主节点的同步处理压力过大而成为瓶颈。为了解决这个问题,redis还支持了从slave节点分发的能力:

Redis的主从模式重点在于解决整体的承压能力,利用从节点分担读取操作的压力。但是其在容错恢复等可靠性层面欠缺明显,不具备自动的故障转移与恢复能力:

  • 如果slave从节点宕机,整个redis依旧可以正常提供服务,待slave节点重新启动后,可以恢复从master节点的数据同步、然后继续提供服务。
  • 如果master主节点宕机,则redis功能受损,无法继续提供写服务,直到手动修复master节点方可恢复。

当然,master节点故障后,也可以手动将其中一个从节点切换为新的master节点来恢复故障。而原先的master节点恢复后,需要手动将其降级为slave节点,对外提供只读服务。

实际使用的时候,手动故障恢复的时效无法得到保证,为了支持自动的故障转移与恢复能力,Redis在主从模式的基础上进行优化增强,提供了哨兵(Sentinel)架构模式。

哨兵(sentinel)

哨兵模式是在现代自动化系统里面常见的一种模式。比如特斯拉汽车就配置了哨兵模式,当车辆停车锁定并启动哨兵模式时,会通过车辆四周的摄像头持续的监控车辆四周的环境,如果发现异常则启动报警系统。

同样地,在软件架构领域,也可以通过设定一些主进程之外的辅助进程,充当“哨兵”的角色时刻监控着主服务,一旦主服务出现异常则进行报警或者自动介入辅助故障转移,以最大限度的保证系统功能的持续性。

Redis的哨兵模式,就是在主从模式的基础上,额外部署若干独立的哨兵进程,通过哨兵进程去监视者Redis主从节点的状态,一旦发现主节点宕机,则哨兵可以重新从剩余slave节点中推选一个新的节点并将其升级为master节点,以此保证整个系统功能可以正常使用。

比较典型的一个Redis sentinel部署场景是“一主二从三哨兵”的组合,如下:

哨兵可以准实时的监控着组网内所有的节点的状态信息,如果判定master节点宕机之后,所有的sentinel节点会一起推选出一个新的master节点。由于sentinel哨兵节点需要承担着master节点推选的责任,所以实施的时候要去sentinel节点个数必须为基数(比如3个、5个等),这是为了保证投票的时候不会出现平局的情况。

在哨兵模式下:

  1. 如果Redis的master节点宕机之后,Sentinel监控到之后,需要先判定确认master节点已经宕机,然后会从剩余存活的slave节点中投票选出一个新的节点作为master节点。
  2. Sentinel监控到此前宕机的master节点重新恢复之后,会将其作为slave节点,挂到现有的新的master节点下面。

哨兵模式有效的解决了高可用的问题,保证了主节点的自动切换操作,进一步保障了Redis缓存节点的可靠性。但是,不管是哨兵模式还是主从模式,其增加的多台部署机器,都仅仅是扩展其承压能力与可靠性,并没有解决分布式场景下对于集中缓存容量的焦虑 —— 只能适用于数据量有限的场景。

成年人的世界总是贪婪的。如果我们既想要保证Redis的可靠性与承压性,还想要突破容量上的限制,就需要Redis的集群模式登场了。

集群(cluster)

Redis提供了去中心化的集群部署模式,集群内所有Redis节点之间两两连接,而很多的客户端工具会根据key将请求分发到对应的分片下的某一个节点上进行处理。

一个典型的Redis集群部署场景如下图所示:

在Redis集群里面,又会划分出分区的概念,一个集群中可有多个分区。分区有几个特点:

  1. 同一个分区内的Redis节点之间的数据完全一样,多个节点保证了数据有多份副本冗余保存,且可以提供高可用保障。
  2. 不同分片之间的数据不相同。
  3. 通过水平增加多个分片的方式,可以实现整体集群的容量的扩展。

按照Cluster模式进行部署的时候,要求最少需要部署6个Redis节点(3个分片,每个分片中1主1从),其中集群中每个分片的master节点负责对外提供读写操作,slave节点则作为故障转移使用(master出现故障的时候充当新的master)、对外提供只读请求处理。

集群数据分布策略

Redis Sharding(数据分片)

Redis Cluster前,为了解决数据分发到各个分区的问题,普遍采用的是Redis Sharding数据分片)方案。所谓的Sharding,其实就是一种数据分发的策略。根据key的hash值进行取模,确定最终归属的节点。

使用Redis Sharding方式进行数据分片的时候,当集群内数据分区个数出现变化的时候,比如集群扩容的时候,会导致请求被分发到错误节点上,导致缓存命中率降低

如果需要解决这个问题,就需要对原先扩容前已经存储的数据重新进行一次hash计算和取模操作,将全部的数据重新分发到新的正确节点上进行存储。这个操作被称为重新Sharding,重新sharding期间服务不可用,可能会对业务造成影响。

一致性Hash

为了降低节点的增加或者移除对于整体已有缓存数据访问的影响,最大限度的保证缓存命中率,改良后的一致性Hash算法浮出水面。

通过一致性Hash算法,将所有的存储节点排列在首尾相接的Hash环上,每个key在计算Hash后会顺时针找到最近的存储节点存放。而当有新的分区节点加入或退出时,仅影响该节点在Hash环上顺时针相邻的后续一个节点。

当然咯,如果Hash圆环上的分区节点数太少,可能会出现数据在各个分片中分布不均衡的情况,也即出现数据倾斜

为了解决这个问题,引入了虚拟节点的机制,通过增加虚拟节点,来实现数据尽可能的均匀分布在各个节点上。

上图中,A1、A2实际上都对应真实的A分区节点,而B1、B2则对应真实的B分区节点。通过虚拟节点的方式,尽可能让节点在Hash环上保持均分,实现数据在分区内的均分。

Hash槽

不管是原本的Hash取模,还是经过改良后的一致性Hash,在节点的新增或者删减的时候,始终都会出现部分缓存数据丢失的问题 —— 只是丢失的数据量的多少区别。如何才能实现扩展或者收缩节点的时候,保持已有数据不丢失呢?

既然动态变更调整的方式行不通,那就手动指定咯!Hash槽的实现策略因此产生。何为Hash槽?Hash槽的原理与HashMap有点相似,共有16384个槽位,每个槽位对应一个数据桶,然后每个Redis的分区都可以负责这些hash槽中的部分区间。存储数据的时候,数据key经过Hash计算后会匹配到一个对应的槽位,然后数据存储在该槽位对应的分片中。然后各个分区节点会与Hash槽之间有个映射绑定关系,由指定的Redis分区节点负责存储对应的Has槽对应的具体分片文件。

数据查询的时候,先根据key的Hash值进行计算,确定应该落入哪个Hash槽,进而根据映射关系,确定负责此Hash槽数据存储的redis分区节点是哪个,然后就可以去做对应的查询操作。

执行数据节点增加的时候,需要手动执行下处理:

  • 为新的节点分配新其负责的Hash槽位区间段;
  • 调整已有的节点的Hash槽位负责区间段;
  • 将调整到新节点上的hash槽位区间段对应的数据分片文件拷贝到新的节点上。

这样,就不会出现已有数据无法使用的情况了。鉴于Hash槽的自主可控性以及节点伸缩场景下的优势,其也成为了Redis Cluster中使用的方案。

小结回顾

好啦,关于Redis部署模式的演进探讨,就聊到这里了。通过本篇文章,我们也可以感受出集中式缓存相对本地而言,在实现与设计机制上要更加的复杂,因为需要考虑与解决多方面的问题,比如可靠性、承压性、容量以及后期的水平扩容能力等等,而这些也都是一个合格的集中式缓存所必须要具备的基本品格。

那么,了解Redis对于集中式缓存在节点安全性与扩展性上的实现后,如果让你来设计一个集中缓存的话,你会采用何种方式来保证其可靠性与后续的扩展性呢?欢迎评论区一起交流下,期待和各位小伙伴们一起切磋、共同成长。

📣 补充说明

本文属于《深入理解缓存原理与实战设计》系列专栏的内容之一。该专栏围绕缓存这个宏大命题进行展开阐述,全方位、系统性地深度剖析各种缓存实现策略与原理、以及缓存的各种用法、各种问题应对策略,并一起探讨下缓存设计的哲学。如果有兴趣,也欢迎关注此专栏。

我是悟道,聊技术、又不仅仅聊技术~

如果觉得有用,请点赞 + 关注让我感受到您的支持。也可以关注下我的公众号【架构悟道】,获取更及时的更新。

期待与你一起探讨,一起成长为更好的自己。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
暂无评论
推荐阅读
Circos图神器--circlize包
circlize包是由德国癌症中心的华人博士Zuguang Gu开发,这个R包包含两个文件,一个是介绍绘制简单圈图的方法,另一个专门介绍基因组数据绘制圈图。
作图丫
2022/03/29
5.4K0
Circos图神器--circlize包
肿瘤免疫细胞浸润与临床相关性分析
Profiles of immune infiltration in colorectal cancer and theirclinical significant: A gene expression- based study
DoubleHelix
2020/04/07
6.9K0
R代码-九象限图绘制
在多组学联合分析中,需要用得到九象限图来对两个组学获得得基因结果进行可视化,例如下面这样得,因此这两天主要是对这个内容进行整理。
小胡子刺猬的生信学习123
2022/09/08
2.2K1
R代码-九象限图绘制
使用corrplot包绘制相关性图及美化!
R语言的corrplot包提供了一种可视化相关矩阵的探索性工具,支持自动变量重排序以帮助发现变量间的隐藏模式。
生信医道
2025/04/08
2800
使用corrplot包绘制相关性图及美化!
如果你觉得相关性热图不好看,或者太简陋
就有粉丝提问,把单细胞亚群使用 AverageExpression 函数做成为了亚群矩阵,是不是忽略了单细胞亚群的异质性呢?毕竟每个单细胞亚群背后都是成百上千个具体的细胞啊。代码如下所示:
生信菜鸟团
2021/07/29
4730
如果你觉得相关性热图不好看,或者太简陋
R- 组合图(折线+条形图)绘制
就是下面这张图,在途中用条形图展示了不同季节样本浮游动物的组成情况,同时使用带误差棒的折线图来表示浮游动物生物量的变化,相当于在一幅图中同时展示了群落的相对丰度和绝对丰度。
DataCharm
2021/02/22
3.5K0
R- 组合图(折线+条形图)绘制
【画图】如何批量展现基因表达相关性?
现在已经有明确的实验证明,跟SARS病毒一样,新冠状病毒2019-nCoV与宿主细胞的ACE2受体结合[1]。上次教程已经给大家演示了,GTEx数据库有人各组织中基因表达谱数据,下载整理这个数据可以绘制出ACE2受体在人体组织中的表达量情况以及可能的功能有哪些。
Chris生命科学小站
2023/02/28
4890
【画图】如何批量展现基因表达相关性?
R语言绘制圈图、环形热图可视化基因组实战:展示基因数据比较
heatmap()的输入应该是一个矩阵(或者一个将被转换为单列矩阵的向量)。如果矩阵被分割成组,必须用split参数指定一个分类变量。注意spilt的值应该是一个字符向量或一个因子。如果它是一个数字向量,它将被转换为字符。
拓端
2021/09/29
5.4K0
【工具】NPM用最接近配对校正组学数据的潜在批效应
批效应(BEs)是组学数据中的主要噪声源,经常掩盖真实的生物信号。BEs在现有数据集中仍然很常见。目前的BE校正方法大多依赖于特定的假设或复杂的模型,可能无法充分检测和调整BE,从而影响下游分析和发现能力。为了解决这些挑战,我们开发了NPM,这是一种基于最近邻匹配的方法,可以调整BEs,并且在广泛的数据集中可能优于其他方法。
生信学习者
2025/04/02
900
基于直方图和散点图延伸出来的其他绘图细节
图形是一个有效传递分析结果的呈现方式。R是一个非常优秀的图形构建平台,它可以在生成基本图形后,调整包括标题、坐标轴、标签、颜色、线条、符号和文本标注等在内的所有图形特征。本章将带大家领略一下R在图形构建中的强大之处,也为后续更为高阶图形构建铺垫基础。
1480
2019/07/01
6570
基于直方图和散点图延伸出来的其他绘图细节
R语言画图
R自带的画图工具,R绘图基础图形系统的核心,plot()函数是一个泛型函数,使用plot时真正被调用的时函数依赖于对象所属的类。
靓且有猫
2024/07/21
1822
R语言入门之折线图
在R语言中可以使用基本绘图函数lines(x, y, type=)来绘制线条,这里参数x和y分别是数值型向量,代表着横坐标和纵坐标的数据,参数type=主要是用来控制线条的类型。
生信与临床
2020/08/06
2.2K0
R语言入门之折线图
R in action读书笔记(15)第十一章 中级绘图 之二 折线图 相关图 马赛克图
> plot(t1$age,t1$circumference,xlab="Age(days)",ylab="circumference (mm)",main="orange tree 1growth")
Ai学习的老章
2019/04/10
6990
R in action读书笔记(15)第十一章 中级绘图 之二 折线图 相关图 马赛克图
Shapes and line types for R
Solution Note that with bitmap output, the filled symbols 15-18 may render without proper anti-alia
学到老
2018/03/16
1.5K0
Shapes and line types for R
「R」自己动手进行R基础绘图
基本绘图和R本身一样古老,但对大多数用户来说,它仍然是神秘的。他们可能使用plot(),甚至知道其参数的完整列表,但大多数人从未完全理解它。本文试图通过为外行提供友好的介绍来揭开基础图形的神秘面纱。
王诗翔呀
2022/12/30
1K0
「R」自己动手进行R基础绘图
R-三维散点图绘制绘制
上期我们说了气泡图。如果我们将气泡图的三维数据绘制到三维坐标系[1]中,通常称其为三维散点图,即用在三维X-Y-Z图上针对一个或多个数据序列绘出三个度量的一种图表。
DataCharm
2021/02/22
2.4K0
R-三维散点图绘制绘制
R语言画图par() 函数参数详解
R有着非常强大的绘图功能,我们可以利用简单的几行代码绘制出各种图形来,但是有时候默认的图形设置没法满足我们的需要,甚至会碰到各种各样的小问题:如坐标轴或者标题出界了,或者图例说明的大小或者位置遮挡住了图形,甚至有时候默认的颜色也不能满足我们的需求。如何进行调整呢?这就用到了“强大”的函数par()。我们可以通过设定函数par()的各个参数来调整我们的图形,这篇博文就是对函数par()的各个参数进行一下总结。
孙小北
2024/01/30
4090
生存资料校准曲线的绘制
前面我们已经讲过logistic模型的校准曲线的画法,这次我们学习生存资料的校准曲线画法。
医学和生信笔记
2022/11/15
8860
生存资料校准曲线的绘制
R语言︱画图
point加点;axis右边坐标轴,mtext右边坐标轴的名称,text给出本文。
悟乙己
2019/05/26
1.3K0
R语言入门系列之二
在进行正式的数据分析之前,通常要对数据进行处理。而读取数据仅仅是最简单的,之后还要进行数据的筛选、排序、转换等。数据框是最方便的数据存储、管理对象。R有很多内置的示例数据集包括向量、矩阵数据框等,可以使用data()进行查看,接下来我们以R内置数据mtcars(32辆汽车在11个指标上的数据)为例进行分析,如下所示:
SYSU星空
2022/05/05
4.2K0
R语言入门系列之二
推荐阅读
相关推荐
Circos图神器--circlize包
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档