CubeFS存储技术揭秘(3)— 均衡、巡检与故障自愈

01 背景

CubeFS的纠删码存储子系统(BlobStore),是一个高可靠、高可用、低成本、支持EB规模的独立Blob存储系统。通过之前分享的系列文章大家对纠删码子系统已经有了深入了解,本文将继续带领大家探讨更多内部实现细节。

对于EB级规模的集群而言,磁盘故障、节点宕机、机器过保等故障是一种常态,可能每天都在发生,在故障发生后如何快速恢复以及在故障发生前如何及时预警是存储系统在设计过程中需要着重考虑的。

Scheduler模块是数据均衡、巡检以及故障自愈等任务的管理中枢,下面将从这三个场景为入口介绍其内部实现。

02 名词解释

在介绍具体实现细节之前,我们将先引入一些关键名词以方便大家在阅读过程中进行对照查询。

Volume:卷,逻辑存储单元,有固定容量上限,VolumeID为其唯一标识,由ClusterManager统一创建、分配与销毁,不同的卷支持不同EC模式。

Chunk:Volume的基本组成单元,是存储数据的容器,对应磁盘上的一段实际物理存储空间,ChunkID为其唯一标识,由BlobNode负责创建、销毁。多个Chunk组织成一个Volume,由ClusterManager维护其绑定关系。

Blob:Blob是上传数据流被切分后的数据片,BlobID为其唯一标识,由ClusterManager统一分配管理,保证全局唯一。

Shard:是EC条带数据的组成单元,Blob写入卷时,对应切分成多个块分别写入到卷中的各个Chunk中,每一个小数据块称为Shard(EC根据数据的组织方式不同,大体分为两类:条带EC:一个对象根据EC模式,拆分成数据块+校验块进行存储;块EC:多个对象组成固定大小的数据,然后根据EC模式拆分成数据块+校验块存储)。

修补:对象级别(Blob)的数据修复,当Blob中的Shard存在数据缺失或者损坏时会发起数据修补流程。

均衡:Chunk级别的数据迁移,保障集群中各个节点Chunk数相对均衡。

磁盘修复:磁盘级别的数据修复,会将磁盘上的所有Chunk数据修复并打散迁移至集群中其他正常节点。

磁盘下线:磁盘级别的数据迁移,会将磁盘上的所有Chunk打散迁移至集群中其他正常节点。

标删/删除:数据删除流程分为两阶段,第一步先标删,当Blob中的所有Shard标删成功之后,执行第二步实际删除,所有Shard都删除成功之后才算成功。

巡检:分为元数据巡检(卷级别数据缺失巡检,判断卷中的Blob是否缺失对应Shard)以及数据巡检(Shard级别数据巡检,判断Shard数据是否缺失或损坏)。

03 数据均衡

为什么需要

谈数据均衡之前我们先谈下数据不均衡出现的场景及影响,对于一个大规模的分布式存储系统而言,扩缩容往往是不可避免。以扩容为例,随着业务量的持续上涨,集群的负载也会越来越高,需要通过扩容的方式来满足实际业务需求,新节点的加入使得集群内数据分布不均造成数据倾斜。于此同时,集群的读写压力可能也会不均衡导致部分节点负载较高(新扩容节点会承担更多新数据的写入)。为了解决这类问题,一般都会引入数据均衡机制将集群内数据进行重新分布。

BlobStore集群由一个个卷(volume)组织用户数据,不同的卷可能为不同的纠删码模式,一个卷由N+M个卷单元(chunk)组成(如果有本地校验块的话,则是N+M+L个卷单元),一个chunk对应磁盘上的一个文件,chunk大小是有上限的(最大为16GB),换而言之一块磁盘上的chunk数目是固定的。

磁盘上的chunk用完可以分为两种情况:

  • 磁盘空间已经用完,即每个chunk均写满,这个时候对应磁盘只能提供读,无法提供写(随着业务数据的删除,删除空间被回收,又会继续提供新的写能力,但是仍然无法组织出新卷);

  • 磁盘空间未用完,但是chunk数已用完,此时磁盘还能正常提供读写,但是无法提供chunk组织出新卷。

当出现chunk数用完的时候,是需要通过扩容的方式来解决。

如何实现

如何安全、高效的实现数据均衡是我们在设计实现中着重需要考虑的。

  • 安全,数据在均衡过程中需要保证有效数据不会丢失;

  • 高效,尽量挪动最少的数据量以达到数据均衡效果。

识别不均衡

Scheduler以idc为粒度维护着整个集群的数据分布情况,判断数据是否均衡主要是看各个磁盘上的可用chunk数的分布,如图所示,大部分磁盘的可以用chunk数在200~340区间,分布相对比较均衡。

如果集群有扩容新节点,则可能出现如下分布状态,整体分为三个区间 [0,220],[275,385],[990,1045],此时整个集群数据分布不均衡,可以开启均衡策略。

均衡触发条件(需同时满足):

1、均衡开关打开

2、满足均衡策略

  • 集群中磁盘最小可用chunk数小于min_disk_free_chunk_cnt,说明对应磁盘可能后续无法组织出新卷;

  • 集群中磁盘最大可用chunk数大于等于max_disk_free_chunk_cnt,该条件是必须的,如果集群中最大可用的chunk数也比较小则均衡效果也不明显,还会增加集群整体压力,只能通过扩容来解决。

比如设置

min_disk_free_chunk_cnt=55,max_disk_free_chunk_cnt=990,则集群会触发自动均衡。

选择均衡源

均衡的目标是使得集群中所有的磁盘都有可用chunk,以最大限度的利用所有节点(磁盘)能力,所以在挑选均衡源时会遵循以下策略:

  • 选择可用chunk数最小的磁盘;

  • 挑选磁盘中chunk大小最小的chunk,根据chunk大小对磁盘上的所有chunk排序,挑选数据量小且对应卷为idel的卷,以便快速迁出原始chunk。

选择均衡目标

在选择迁移目标时候会根据磁盘所剩可用chunk数高概率选中可用chunk数多的磁盘以快速均衡磁盘可用chunk数(此处分配目标策略由ClusterManager管理)。

迁移数据

Scheduler将迁移任务初始化完成后(主要选中迁移的源与目标)BlobNode拉取任务并执行数据迁移,数据迁移过程也会对数据进行智能修复以提高数据的可靠性,数据迁移主要分为以下几步:

  • 确定迁移bid基准列表,基准不一定等于源chunk的bid列表,可能比源chunk中的bid多(比如某个bid恰好写该chunk失败,但是其他chunk写成功满足quorum机制,这时会将缺失的bid补齐),也可能比源chunk中bid少(如果发现对应bid已经标删,则会跳过该bid的迁移);

  • 读源,根据迁移bid列表读取对应bid数据,优先直读,如果读源失败则会采用修复读的方式获取数据;

  • 写目标,向对应目标chunk发起数据写请求。

如图所示,假定迁移源chunk为vuid20,对应bid列表为{bid0,bid2,bid3},通过数据迁移会将缺失的{bid1,bid4}修复回来。

建议

一般情况下我们不需要打开均衡开关,数据写入会均匀的分布在集群中各个节点,而磁盘chunk不足时候往往可以通过扩容解决,只有在一些极端场景,比如集群还有空间但是chunk已经用完无法组织新卷或者chunk迁移等无法分配新chunk时才需要打开。

04 巡检

巡检可以让集群及时发现缺失或损坏数据,根据巡检的方式可以分为两类:元数据巡检与数据巡检,两者相辅相成共同保障数据安全可靠。

元数据巡检

为什么需要

元数据巡检是针对卷级别的巡检,由Scheduler发起(单机存储引擎BlobNode无法发现卷级别的数据缺失)。元数据巡检可以及时发现数据缺失,可能有以下几种情况导致数据缺失。

1、业务写数据在满足quorum的前提下,剩余数据块写入失败;

  • 投递修补消息失败

  • 投递修补消息成功,但是巡检时数据还未修补

2、业务所有数据块写入成功,后期存储引擎自身元数据缺失或损坏;

3、业务写入失败投递删除消息,实际数据写入份数满足quorum,但是巡检时数据未删除。

如何实现

巡检的关键在于如何判断数据缺失,并尽可能的修复缺失数据以提高数据的可靠性。

注意巡检过程需要做到只修不删,对于巡检过程中发现的垃圾数据不做清理,方便后续问题追溯。

在巡检卷时,会向卷中所有chunk发起bid列表查询,根据返回结果判断是否属于数据缺失,以上图为例说明在巡检中遇到的几种场景:

  • bid在卷中所有chunk均存在,则bid正常(如图中bid1);

  • bid中存在标删,说明已经发起删除请求,对应bid即使有缺失也不需要修补,跳过(参考图中bid2,bid3情况);

  • bid中存在缺失,且剩余有效shard满足纠删码计算最小份数,则属于数据缺失情况,生成修补消息(如图中bid4);

  • bid中存在数据缺失,但是不满足可恢复数据份数,属于孤本数据,没办法判断是当时数据写成功之后数据丢失还是原本就没写成功,所以巡检过程中会记录对应bid信息,而不是执行删除(如图中bid5所示),不过基本上都是因为当时数据写失败造成,因为数据写入时候会保证quorum足够大。

数据删除有分为两阶段执行,第一步数据标删,当所有数据均标删成功才执行数据删除,当所有数据删除成功之后删除消息才算消费成功,图中删除状态其实跟缺失状态的现象是一样的,对应bid都不存在。假设删除不分为两阶段执行,则可能出现已经删除的数据又被巡检发现缺失而修补回来。

数据巡检

为什么需要

虽然说元数据巡检能发现数据缺失,但是数据本身的损坏还是无法及时发现。一般会有以下几种场景发现数据损坏:

  • 业务读,当正常业务读时发现数据损坏,可以触发修补;

  • 后台读,在执行后台任务的时候如果有数据损坏也可以触发修补;

  • 巡检,定期巡检自身数据,如果有损坏可以触发修补。

前面两种策略可以快速的修复“热数据”,不过对于一些访问比较少的数据而言可能长期得不到修复,所以需要与存储引擎自身的数据巡检相结合以解决数据损坏问题。

如何实现

数据的巡检由BlobNode单机存储引擎触发即可,根据自身的元数据列表,读取相关数据,如果数据读取发现损坏,则会投递修补消息等待后台任务异步修补(数据的写入是先写数据,再写元数据,所以如果元数据存在则对应数据也应该存在)。

05 故障自愈

这里的故障主要分为两类:磁盘级别的故障与对象级别数据块(shard)的故障,磁盘级别的故障由磁盘修复流程恢复数据,而对象级别的数据损坏则是通过数据修补流程快速修复响应数据块,下面将分别进行介绍。

数据修补

数据修补主要是针对对象级别的数据修复,主要有以下场景会触发数据修补

1、数据写入,在纠删码模式下数据写入成功的份数满足quorum机制即认为数据写入成功(假定是N+M模型,一般是需要写入成功N+K份,其中az数<k<m),在保障数据高可靠的同时能提供在线写入服务的高可用,对于剩下的m-k份数据块会后台< span="">异步写入(可以有效避免写入尾延时),如果剩余数据块写入失败则会通过Proxy模块投递修补消息,等待后台流程异步修补对应缺失数据块;

2、数据巡检,数据巡检分为两类:

  • 元数据巡检,由Scheduler发起比对卷中所有chunk的元数据信息,发现缺失数据则投递修补消息;

  • 数据巡检,由BlobNode发起读取自身chunk数据(每个数据小段会有一个crc,通过比对crc发现数据异常),如果数据有异常则投递修补消息。

Scheduler异步消费消息中间件中的修补消息生成修复任务,然后将任务下发给BlobNode,由其执行修补

如图所示,假定3+2模式中,有两个数据块需要修复,Scheduler生成修补任务之后将其下发给BlobNode,通过读取vuid0,vuid10以及vuid40的数据然后ec计算即可得到缺失的数据并写入对应目标节点。

磁盘修复

磁盘修复相对于数据修补而言要复杂一些,待修复磁盘上可能存在很多的chunk,每个chunk包含很多shard,磁盘修复的速度也影响着数据的可靠性,所以在磁盘修复时候会利用整个集群的能力进行数据修复。

如图,以卷1为例,包含12个数据chunk,9个全局校验chunk与3个本地校验chunk,不同卷的az分布可能不同,比如卷1中前四个数据分布在AZ2,卷2的前四个chunk可能分布在AZ1或AZ3。同一个卷的chunk一定分布在不同的磁盘,而一块磁盘上的chunk属于不同卷。

在做磁盘损坏的数据修复时,首先会为坏盘上的所有在线chunk列表生成迁移任务,一个chunk对应于一个迁移任务(跟均衡任务一样),BlobNode在执行磁盘修复任务时如果有本地校验块则会优先读取本机房的数据进行修复,以减少跨机房的带宽消耗(一般一个卷坏一个chunk的概率比较大,所以能最大程度利用本az数据进行修复),如果本AZ修复失败则会利用集群的整体能力进行跨AZ修复(当前修复策略是先读全局数据块,份数不够再读全局校验块)。

如图所示,假定卷1中chunk1所在磁盘损坏,则为其生成一个修复任务,由于存在本地校验块所以在修复时候会优先在本AZ内修复,即读取AZ2中其他7个chunk数据进行纠删码修复,如果修复失败才会走跨AZ读全局块修复。

节点下线

当出现机器过保或集群缩容节点下线等情况时,需要将对应节点上的数据迁移至其他其他节点,一般也有几种策略:

  • 设置坏盘通过磁盘修复流程对数据进行迁移;

  • 设计节点下线流程对数据进行迁移。

节点下线流程正常情况下优先直读源数据,如果读取失败才通过纠删码修复流程,相比于磁盘修复可以避免大量跨机房数据读造成的带宽、计算资源等浪费问题,同时还提升了数据迁移速度。

节点下线流程大体上与磁盘下线类似,首先会为磁盘上的所有有效chunk生成对应下线任务,后续转变为chunk级别的数据迁移,流程与均衡或者磁盘修复类似,这里就不在赘述。

06 总结

后台管理模块主要围绕数据均衡、巡检以及故障自愈等场景展开设计,旨在保障数据的安全可靠,每个流程都是集群中不可或缺的一环,总结来说主要分为两个方向:

  • 如何尽早发现数据损坏:数据损坏时间越长,数据丢失风险就越大,所以需要在模块设计的各个阶段考虑数据损坏问题,比如正常读、写关键流程上快速发现“热”数据损坏,通过数据或元数据的离线巡检全面发现数据损坏等;

  • 如何快速修复损坏数据:比如磁盘损坏、数据损坏、磁盘或节点过保下线等异常,需要安全快速将其数据恢复至健康磁盘或节点。

CubeFS简介

CubeFS于2019年开源并在SIGMOD发表工业界论文,目前是云原生计算基金会(CNCF)托管的孵化阶段开源项目。作为新一代云原生分布式存储平台,兼容S3、POSIX、HDFS等协议,支持多副本和纠删码引擎,提供多租户,多AZ部署、跨区域复制等特性;适用于大数据、AI、容器平台、数据库及中间件存算分离,数据共享、数据保护等广泛场景。

GitHub:https://github.com/cubefs

微信群:搜索并添加微信号blkleaf或mervinkid联系,注明您的来意

公众号:微信搜索“CubeFS官微”

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值