打造具备极致容灾能力的对象存储

本文涉及的产品
对象存储 OSS,20GB 3个月
对象存储 OSS,内容安全 1000次 1年
对象存储 OSS,恶意文件检测 1000次 1年
简介: 本文介绍本地冗余,做了哪些容灾设计、应对AZ故障的ZRS(同城冗余)产品的容灾设计以及应对Region故障的跨区域复制功能。

1.背景


时间进入2023年,分布式存储又向何处去呢?

哪些场景、业务创新会成为新的突破口呢?

如何帮助传统产业更好应对海量数据增长和数据创新的挑战?

2023年3月10日,由百易传媒(DOIT)主办、上海市计算机学会与上海交通大学支持的第六届分布式存储高峰论坛(Distributed Storage Forum 2023)于线上举行,十多位业界专家、厂商代表与近万名观众就时下热点关注的话题进行分享、互动和交流。


image.png


本文的题目是:“如何打造具备极致容灾能力的对象存储”。


容灾是分布式存储领域的一个关键问题。


最基础的是服务器容灾,这是所有对象存储产品都要解决的问题。


进一步,就是AZ(Availability Zone)级故障容灾,AZ也就是可用区。通常一个可用区会映射到一个或者多个数据中心。一个AZ和其他AZ在制冷、供电等方面都是故障域隔离的。几大云厂商也都提供支持AZ级容灾的对象存储产品。


可能有同学会问,做AZ级容灾是不是有必要?大家如果去网上去搜索一下就会发现,各大云厂商的AZ级故障还是时有发生的,包括一些不可抗灾害或者制冷、供电中断等故障。从底层逻辑上来讲,AZ级故障是不可能彻底避免的。对于一些高可用的应用,采用具备AZ级容灾能力的存储产品还是非常有必要的。


Region故障也是同样的道理。每个AZ之间会间隔几十公里,但是在一些极端场景,比如高等级地震的时候,那同时影响到一个Region的多可用区也是有可能的。比如最近土耳其7、8级地震,它是有可能导致Region级故障的。各家厂商也有提供一些应对Region故障的产品或者说解决方案,对象存储OSS也有类似的产品,后面会介绍。


本次分享首先会介绍本地冗余,也就是LRS(本地冗余)这个产品做了哪些容灾设计,其次,我会介绍我们应对AZ故障的ZRS(同城冗余)产品的容灾设计,第三部分是应对Region故障的跨区域复制功能。在第二、第三部分我分别以案例深入介绍我们在技术上做的一些改进或者设计。最后分享我们是如何以智能运维平台来应对生产过程中系统长时间运行以后架构腐化的问题。


2.. LRS(本地冗余产品)的容灾设计

image.png

上图左边是我们OSS系统模块的划分图,从上到下大致可以分为四层。


用户请求进来之后,首先会到达我们的负载均衡,也就是AliLB,AliLB是阿里自研的高性能的负载均衡产品,它是基于LVS原理的。


往下请求会来到业务层,在这一层主要是做协议的解析、各种各样的业务功能的实现。这两层我们都是一个无状态的设计。在这种无状态的服务里面如何做高可用的呢?我们会把它的部署按机架来打散并保证两个机架故障情况下,它的服务能力还是足够的。


再往下,请求就会来到索引层,索引层我们叫做KV,是一个Master Server结构。每个Server又根据字典序划分为多个分区,它的Master跟每个分区的Server都是采用Raft协议实现的一致性组。


底下就是存储服务盘古,它跟KV类似,也是一个Master Server的结构。区别是它的Server没有采用一致性组的架构,主要是性能考虑。另外在高可靠上是通过副本或者EC机制来做的。


在LRS产品里,阿里云整体的容灾设计目标是希望做到两个机架故障不影响服务的可用性和可靠性。


刚才已经提到了无状态服务,对有状态服务的话,他们的一致性组,我们都是采用五节点部署的。这五个节点会打散部署在至少五个机架上。这样显而易见:如果说故障两个机架,还是有多数节点存活,还可以提供服务。


数据方面,我们有两种数据的存放形式,有三副本,也有EC。三副本的话,只要做了机架打散,显然是可以实现两机架的容灾的。对于EC,我们也会保证它的校验块的数量大于等于二。同样也是做机架打散,能实现两个机架故障不影响可用性可靠性。


除了这些数据的分散方式,我们还做了非常多的其他的设计来保障高可用。比如数据分片是做全机群打散的,这样做有什么好处呢?如果一台服务器发生故障,如果做全打散的话,是可以利用这个集群里剩余的所有机器来并行的做数据修复,这样缩短了数据的重建时间,相应的也就提高了可靠性。


另外,我们也会刚性的保留足够的复制带宽。所有的这些,包括集群水位,副本的配置,包括打散方式,还有复制带宽,我们都会用一个模型来去计算并且测试验证它的可靠性,保障设计达到12个9的可靠性。


3. ZRS(同城冗余)产品容灾设计


通俗来说,OSS ZRS(同城冗余)产品,也叫3AZ型态。它和LRS最主要的区别就是在容灾设计目标上,LRS要容忍两个机架故障,ZRS则是要保证一个AZ外加一个机架故障时不影响可靠性可用性。


image.png


稍微提一下,假设你一个AZ故障发生以后,如果修复时间相对比较长,那再坏一台机器的概率还是比较高的。如果在容灾设计上只容忍1AZ的话,最后因为AZ修复期间单台服务器的故障影响了可用性,那就有点得不偿失了,所以我们在设计上特意采用了1AZ加额外一机架的故障容忍的设计目标。


再来讲讲怎么实现容灾设计的。


在模块划分上ZRS和LRS基本是一样的。主要的区别是模块的打散方式,在LRS里都是跨机架打散,在ZRS里,我们会把它升级到跨AZ打散,所有的模块都是跨AZ部署的。当然在AZ内还是会做机架级的打散的。


关于有状态服务。有状态服务的一致性组在LRS 都采用5节点部署,ZRS产品里面就会变为9节点。9个节点会均匀打散到3个AZ,每个AZ有3个节点。这个设计是可以容忍4个节点故障的。也就是说可以容忍“1AZ+剩下两个AZ里的某个节点故障”。


在数据的高可靠方面,前面提过我们有3副本的EC。3副本显而易见,只要做了AZ打散,是可以容忍刚才提到的容灾设计目标的。EC是要做比较大的EC配置的重新设计。理论上,3个AZ要容忍1个AZ故障,那数据冗余至少要1.5倍。实际上早期我们采用6+6的EC配置,大家可以理解一个数据集,把它拆分为6个数据块+6个校验块,平均分布到3个AZ,每个AZ有4个块。这样一个AZ故障的时候,一个数据集里还剩余8个块,其实只要有6个就可以恢复数据了。所以,这个时候还可以再容忍2个机架故障,相比于容灾设计目标是有一定的超配。


image.png

当然,做了这样的设计之后,看起来是可以容忍“1AZ+额外1机架故障不影响可用性可靠性”,但实际没这么简单。


实际的运行过程中还要考虑到非常多的其他因素。比如如何解决跨AZ的超高吞吐的带宽需求?AZ间的延迟显然是要比AZ内的延迟高很多,如何通过系统的设计尽量让这个延迟的增加不影响到用户?又比如说在1个AZ故障的时候,本来就有1/3的机器不可服务的,如果还要再做数据重建,那又带来非常大的IO放大。如何保证在AZ故障时候的高质量的服务?是有非常大的挑战的。


接下来以刚才提到的最后这个挑战为例来做一个相对深入的介绍。


下图左边是一个示意图,我们前面提到了,我们早期是用6+6的EC编码。我们采用的是RS的编码。在单个AZ故障的时候剩余8个块提供服务,其中4个数据块+4个校验块。


简单计算一下,在这种AZ故障的情况下,单台机器或者单块磁盘承受的IO压力,相比在故障前日常情况下大概是什么水平。

image.png

发生故障的时候,显而易见是有2/3的数据是可以直接读取的,也就是说1份IO没有放大。另外有1/3是要通过rebuild来做重建的。重建的话,RS编码至少要读6块数据,不考虑额外的校验也要读6块数据才能重建。也就是说有1/3的数据是要读6块才能重建。再考虑故障期间只有2/3的机器提供服务。

右上角有一个简单的算式,可以看到,故障期间每台机器或者每块盘承受的IO压力是日常的4倍。换个角度来解读一下,如果这个机器的IO能力是100%的话,那要保证在故障以后还是高可用的,日常最多只能用到它IO能力的25%。考虑还要留一定的安全水位,假设打个八折,那可能就只有20%了,这个数据显而易见是非常夸张的,给我们带来一个很大的挑战:要么让ZRS产品相比LRS只能提供低的多的IO能力,要不然就是要承受高的多的成本。


正因为有这样的挑战,所以EC的编码方式,尤其是在同城冗余型态下EC的编码方式一直是我们持续投入的研究或者改进的方向,我们也做了非常多的工作,提出了自己独创的AZC的编码,这个编码算法本身也有在顶会中发表论文。

image.png


这里做一个简单的介绍。


简单来说,AZC编码就是把原本1维的EC编码升级成了2维。水平方向,是一个AZ间的编码,我们首先会把一些数据块划分为多个小组。每个小组内,如果以上图左侧的示意图为例,每个小组是“2个数据片+1个校验片”做了一个2+1的RS编码。用小的EC配比有一个好处,在AZ故障的时候重建代价小,相比前面要读6份重建,现在只要读2份就可以了。


当然这种小配比的EC也是有缺点的,代价就是它的容灾能力差,可靠性低。因为只要有2个机架故障,丢掉2个分片,它的数据就无法恢复了,这显然是不可接受的。所以在垂直方向,也就是AZ内,我们又把多个分组内的数据块结合到一起,额外做了一个垂直方向的编码。通常,比如说用12个片,额外再加2-3个校验块做一个RS编码,两者结合起来就能在12个9可靠性的前提下,仍然能保证在AZ故障的时候重建的IO放大是比较小的。


当然AZC也不只是AZ故障重建代价低的好处。通过一些仔细的编码配比的选择,它的数据冗余相比前面提到的6+6 EC也是要好非常多的。


前面也提到,我们会在垂直方向做一个AZ内的RS编码。这也就是说日常情况下,如果AZ内有机器故障,是可以在AZ内本地重建的,可以完全避免跨机房的重建流量。也就是说,AZC编码其实是在AZ的故障重建代价和数据冗余的成本和日常的跨机房重建流量这三个方面取得了一个比较好的平衡。相比6+6 RS编码提升是巨大的,根据这个公式简单算一下,流量放大倍数从4降到了2,换句话说,也就是说IO利用能力提升了整整1倍。


近几年,从ZRS产品业务情况上的观察,越来越多的客户开始重视AZ级容灾能力,使用ZRS的比例越来越高。在香港故障以后,很多客户把他们的数据存储转到了ZRS型态上。很多本身已经在用LRS的客户,也想无缝的升级到ZRS。


针对这些需求,结合前面做的各种技术改进,阿里云推出了两个大的升级。第一,将以前不支持归档型的ZRS 升级到支持归档类型。另外在迁移能力上做了非常多的工作,支持LRS无缝迁移到ZRS,已经在线下以工单的方式帮非常多的客户完成了迁移,产品化的迁移功能也马上会推出。


image.png


前面介绍的是AZ级故障的应对,接下来我介绍一下第三部分。


4. Region故障的应对


Region故障的应对,主要是跨区域复制功能。


image.png

上图左边是一个简单的示意图。


前面提到,我们有服务层OSS Server,也有索引层KV Server。所有的请求在到达KV Server之后,增删改操作都会有一条redolog,而且这个redolog是可以定序的。所以为了实现跨区域复制,首先我们增加了Scan Service,它的功能就是扫描所有的redolog来生成复制任务,并且是可定序的复制任务。


这里要强调一点——我们的复制任务是异步的,它跟用户的前台请求完全解耦,也就是说它出任何问题,是不影响用户的前台业务的。在图里用不同的颜色进行了区分。


有了任务之后,第二个重要的模块就是图里面的Sync Service,它的功能就是把每个复制任务去源端读取数据,通过跨区域复制的专线或者公网把它写到目的端去。除了完成这个复制任务本身以外,也要做很多其他的功能,比如说各种维度的QoS,还有在目的端写入的时候,因为用户自己也有可能直接写入,所以要做一致性的数据冲突的仲裁等等。


image.png


这部分我也挑了一个功能来做一个相对深入的介绍,我选的是RTC功能,顾名思义就是数据复制时间控制。


一句话来表达,开启了RTC以后,OSS会对跨区域复制的RPO时间做一个SLA承诺。在以前如果不开启的话是不提供承诺的。大多数情况下是可以秒级完成复制的,另外,对长尾情况也保证P999的对象可以在10分钟内完成复制。另外,我们还提供了非常多的复制进度的监控,比如复制的带宽量、数据量,复制的延迟情况,剩余多少没有完成的复制任务等等。


为了实现这些,我们后台做了非常多的技术改进。


首先,因为是一个跨区域的复制,所以带宽资源非常宝贵,在带宽资源管理上做了多维度的隔离。首先就是租户间的隔离,任意的用户不能影响到其他的用户。另外,其他的业务的跨区域的流量不能影响到这个RTC服务的流量。以及其他类型的多种维度的QoS隔离。


除了隔离以外,在优先级上也做了非常多角度的划分。最直白的就是开启了RTC,那在复制带宽上就有更高的优先级。另外,在同一个客户的RTC的复制边内,已经延迟了的这些任务,相比刚生成的任务就有更高的优先级等等。


除了物理资源的管理,在架构上也做了很多改造来提升复制的实时性。


举一个例子,OSS的对象,一个对象是可以支持数十T大小的。如果在这个对象上传完成之后才开始复制,那显然不可能做到秒级复制,所以在开启了RTC之后,我们会用更多的IO来保证复制的实时性。简单来说,没开启RTC的时候,我们是在一个PART 上传完成之后触发一个复制任务,如果开启了RTC,那就会在每个PART的1MB或者其他大小的分片上传完之后就会生成一个复制任务。这样才能有比较好的实时性保证。


另外,也做了多种维度的精细化的监控,包括对RPO破线的报警等等。


正是因为所有的这些改进,我们才有信心对客户承诺RPO的SLA 的保障。


5. 防止良好的容灾设计在执行中逐步腐化


前面介绍完了我们对服务器故障、AZ级故障和Region故障容灾上的设计,但是实际的运行过程中也不是这么简单的,就像一个良好的架构设计在执行较长时间之后会有各种各样的腐化问题,容灾设计也是同理。


举一个简单的例子,前面讲了要有IO压力控制,不管是20%还是40%,总是要有一个IO水位的控制的。假设线上用户的业务情况增长短时间突破了容灾水位,如果不及时做扩容的话,那其实就已经丧失了容灾能力了,这就是一个典型的腐化问题。


又比如说前面讲了各种EC、3副本的数据分布,理想的情况它是应该分布均匀的,但如果某个版本的软件在这些数据分布算法上出了bug,那它有可能导致分布不均匀。


所有这些问题都会导致容灾设计失效。


OSS如何应对这些问题呢?我们会做一些常态化的运维演练,再结合监控报警和自动修复功能来解决这些容灾腐化问题。


这些功能主要都是通过我们的智能运维平台提供的,最后一部分会对我们的智能运维平台做一个介绍。


5.1 对象存储OSS智能运维平台-数据湖仓


image.png


运维的基础是数据,要有丰富的数据,才有做智能运维的基础。


在OSS这里,我们通过多年积累,沉淀了非常多的数据。上图左下就是运维平台收集的数据的示意。比如各种各样的监控数据,如网络探针,可以从外部探测,知道某个区域不可用了;比如服务器的角度,有机器的多种维度数据;应用角度,有每个进程,每个模块的日志等各种数据;系统的角度,有内核的内存、CPU、磁盘、进程等等多种维度的数据。


阿里云本身有50多个的横向的支撑系统,有非常多的数据沉淀,我们的运维平台也做了打通。在数据处理上的话也是非常有挑战的。这里以一个最简单的OSS访问日志的例子。我们的访问日志每秒钟有亿级的日志条目,在处理上的压力是非常大的,处理的性能、成本都是问题。我们做了非常多的工作,比如采集端,会在本地做一些加工处理,例如过滤、聚合之类的来缩减数据量。


在缩减完之后,我们会使用阿里云的各种功能非常强大的产品,比如说SLS、Blink来做数据的实时处理。处理的这些结果会存储到ODPS或者OSS自身这样的存储产品里面供后续使用。


对一些离线的数据、复杂的数据处理,我们会用到基于OSS的数据湖方案来处理。


5.2 对象存储OSS智能运维平台:运维动作自动化


如果把这个智能运维平台比作一个人,数据就像是人的眼睛。接下来,我要讲的运维动作有点像人的手脚,给我们提供运动能力。


image.png


在这一块,我们的理念有点像Linux 平台的理念。首先研发同学会把各种各样的原子操作、原子运维动作都做脚本化,有点像Linux里的一个个命令,每个命令只完成一件事情,这些运维动作的原则也是每个脚本只完成一件事情。然后我们的运维平台赤骥提供的工作流功能,有点像Linux里的管道,类似一个个简单的命令,用管道组合起来提供一些复杂的功能。运维平台通过工作流,可以把各种基础的运维动作组合起来,实现一些复杂的运维动作,比如说集群上线,集群下线。


当然,有些运维动作相对来说是比较复杂的。以数据迁移为例,在架构上,通过把一个对象拆成META元数据和 DATA数据两部分,右下角就是一个对象的简单示意,可以看一个 META的KV对结合用户元数据的KV对加若干个数据KV对,就组成了一个对象。通过这样的架构设计,就能实现提供几个基础的运维动作:


第一,可以把一个Bucket数据打散到多个存储集群,每个集群的比例还可以按照需要做不同的调节,不一定完全对等。


第二,可以通过迁移部分数据来做一些灵活的容量调度。


有了眼睛和手脚之后,在大脑的指挥下就可以做一些复杂的高级动作了,对运维来说,也就是说可以完成一些复杂的运维任务。


5.3 对象存储OSS智能运维平台:复杂运维任务


以我们怎么应对容灾腐化的例子来做一个收尾吧。


image.png


前面提到过一个例子,就是当业务压力增长,让某个ZRS集群的IO压力超过了安全水位线,这个时候运维平台首先会收到报警信息。


收到报警信息之后,我们会提前有一些预设的规则,比如报警持续了超过多长时间,报警里面产生的IO压力,用户的IO行为是持续的,而不是一个瞬时的行为。明确了这些信息之后就会做出决策,然后就要做数据的调度来把一部分IO压力迁移到别的集群,来让原本这个集群的IO水位恢复到安全水位。这个时候它就要去调度前面说的那些数据迁移的原子能力来做迁移。这个时候问题就来了:因为数据和IO压力其实不是直接关联的,关系比较复杂,到底要调度哪些数据、调度多少数据才能迁移走想要的那么多IO压力呢?这个又用到了数据,就是前面讲的我们沉淀了各种各样的数据,其中就有用户的每个Bucket的IO行为的用户画像。


右边这张图就是其中某个维度的示意。一个用户Bucket,我们会持续跟踪他读取的行为。举一个例子,比如说你上传了一天内的数据,你到底有多少比例是读它的,1-3天的有多少比例,3天以上的有多少比例。有了这个比例划分,再结合一个用户每天IO行为的总量的变化情况,就可以在后台计算出来,是调度新写入的数据效率更高,还是迁移写入了某个时间以上的的数据效率更高、以及要迁多少。


计算出这个结果之后就开始真正做执行了,通过工作流去把指定的数据搬迁到其他集群之后,原本这个集群的IO压力就恢复到安全水位,等于说靠智能运维平台,研发人员可以把各种约束都沉淀为这样的复杂运维任务来录入智能运维平台上,保证在长时间运行下所有容灾设计都像预期的那样去工作。


作者:闫卫斌,阿里云智能资深技术专家

相关实践学习
借助OSS搭建在线教育视频课程分享网站
本教程介绍如何基于云服务器ECS和对象存储OSS,搭建一个在线教育视频课程分享网站。
相关文章
|
5月前
|
机器学习/深度学习 人工智能 专有云
人工智能平台PAI使用问题之怎么将DLC的数据写入到另一个阿里云主账号的OSS中
阿里云人工智能平台PAI是一个功能强大、易于使用的AI开发平台,旨在降低AI开发门槛,加速创新,助力企业和开发者高效构建、部署和管理人工智能应用。其中包含了一系列相互协同的产品与服务,共同构成一个完整的人工智能开发与应用生态系统。以下是对PAI产品使用合集的概述,涵盖数据处理、模型开发、训练加速、模型部署及管理等多个环节。
|
1月前
|
分布式计算 Java 开发工具
阿里云MaxCompute-XGBoost on Spark 极限梯度提升算法的分布式训练与模型持久化oss的实现与代码浅析
本文介绍了XGBoost在MaxCompute+OSS架构下模型持久化遇到的问题及其解决方案。首先简要介绍了XGBoost的特点和应用场景,随后详细描述了客户在将XGBoost on Spark任务从HDFS迁移到OSS时遇到的异常情况。通过分析异常堆栈和源代码,发现使用的`nativeBooster.saveModel`方法不支持OSS路径,而使用`write.overwrite().save`方法则能成功保存模型。最后提供了完整的Scala代码示例、Maven配置和提交命令,帮助用户顺利迁移模型存储路径。
|
4月前
|
存储 机器学习/深度学习 弹性计算
阿里云EMR数据湖文件系统问题之OSS-HDFS全托管服务的问题如何解决
阿里云EMR数据湖文件系统问题之OSS-HDFS全托管服务的问题如何解决
|
5月前
|
消息中间件 分布式计算 DataWorks
DataWorks产品使用合集之如何使用Python和阿里云SDK读取OSS中的文件
DataWorks作为一站式的数据开发与治理平台,提供了从数据采集、清洗、开发、调度、服务化、质量监控到安全管理的全套解决方案,帮助企业构建高效、规范、安全的大数据处理体系。以下是对DataWorks产品使用合集的概述,涵盖数据处理的各个环节。
|
5月前
|
存储 运维 安全
阿里云OSS的优势
【7月更文挑战第19天】阿里云OSS的优势
242 2
|
5月前
|
存储 API 开发工具
阿里云OSS
【7月更文挑战第19天】阿里云OSS
207 1
|
5月前
|
存储 弹性计算 对象存储
预留空间是什么?阿里云OSS对象存储预留空间说明
阿里云OSS预留空间是预付费存储产品,提供折扣价以锁定特定容量,适用于抵扣有地域属性的Bucket标准存储费用及ECS快照费。通过购买预留空间,如500GB通用预留+100GB标准-本地冗余存储包,用户可优化成本。
228 4
|
5月前
|
人工智能 对象存储
【阿里云AI助理】自家产品提供错误答案。阿里云OSS 资源包类型: 下行流量 地域: 中国内地通用 下行流量包规格: 300 GB 套餐: 下行流量包(中国内地) ,包1年。那么这个是每月300GB,1年是3600GB的流量;还是1年只有300GB的流量?
自家产品提供错误答案。阿里云OSS 资源包类型: 下行流量 地域: 中国内地通用 下行流量包规格: 300 GB 套餐: 下行流量包(中国内地) ,包1年。那么这个是每月300GB,1年是3600GB的流量;还是1年只有300GB的流量?
140 1
|
5月前
|
持续交付 开发工具 对象存储
阿里云云效产品使用合集之构建物如何上传到阿里云OSS
云效作为一款全面覆盖研发全生命周期管理的云端效能平台,致力于帮助企业实现高效协同、敏捷研发和持续交付。本合集收集整理了用户在使用云效过程中遇到的常见问题,问题涉及项目创建与管理、需求规划与迭代、代码托管与版本控制、自动化测试、持续集成与发布等方面。
|
5月前
|
缓存 对象存储 数据安全/隐私保护
阿里云OSS, 跨域请求, No ‘Access-Control-Allow-Origin‘
阿里云OSS, 跨域请求, No ‘Access-Control-Allow-Origin‘
786 0

相关产品

  • 对象存储