如何实现支持百亿级文件的分布式文件存储
1 前言
文件系统是最常用的数据存储形式,所以,常用 Linux 操作系统的用户必然知道 ext4、xfs 等单机文件系统,用 Windows 操作系统的用户也都知道 NTFS 单机文件系统。各种业务场景下,不同的数据都存储于文件系统之上,大量业务逻辑就是基于文件系统而设计和开发的。提供最常用的存储访问方式,这是我们做文件系统的出发点之一。
另一方面,单机文件系统有其明显限制,主要是容量、文件数量限制,以及可靠、可用性限制。单机文件系统毕竟存储空间有限,且掉电或坏盘等故障会带来数据不可达或丢失。通过分布式文件系统解决这些问题,这是我们的出发点之二。
但做分布式文件系统会面临很多挑战,也会面临非常多的选择。
Google GFS 论文面世之后,Hadoop HDFS 随之诞生,HDFS 的选择是处理大文件,面向 MapReduce 这种非在线数据分析业务,重吞吐而非延时,对 HDFS 内部存储的数据进行访问,需要借助其提供的专有命令行和 SDK,意味着它并不是一个通用型的文件系统。它的主要架构是元数据服务(本文统一用 MetaData Service 的缩写 MDS 来指代元数据服务)和数据服务(本文统一用 Data Storage Service 的缩写 DSS 来指代数据服务),其中 MDS 是单点的,单点的 MDS 能做出一致的决策,为了保证 MDS 可靠性,一般会选择再做一个备份。HDFS 的 DSS 则可以是很多个。因为文件大小和形式固定,元数据量不会太大,因而理论上单点 MDS 就可以支撑,不过单 MDS 仍限制了集群的规模。
HDFS 之后,出现了一些其他的开源分布式文件系统,比如 MooseFS。它也是类似的 MDS+OSS 架构,区别于 HDFS 的是,MooseFS 没有对运行其上的业务做假设,它没有假设业务是大文件或海量小文件,也就是说,MooseFS 的定位是像 ext4、xfs、NTFS 等单机文件系统一样的通用型文件存储。其实 MooseFS 底下用的就是单机文件系统,可以认为它只是将多台机器上的多个单机文件系统做了一个“逻辑上”的聚合,之所以这么说,是因为从数据角度,它主要是实现了一个多副本功能,而副本间的数据一致性并没有去严肃地保障。从元数据角度,MooseFS 提供了一个本质上就是单机的 MDS,但为了保证元数据的可靠性,MooseFS 通过某些机制,接近实时地备份了元数据。
另外一个更为知名的开源分布式文件系统就是 GlusterFS 了,相比 MooseFS 等文件系统,GlusterFS 的明显特点是它的“无元”架构,即它没有独立的 MDS,GlusterFS 使用一致性哈希算法去定位元数据和数据。我们在设计和开发自己的文件系统时,并没有选择这样的架构,因为它的缺点非常明显,例如元数据操作性能很差,而文件系统日常使用中,对元数据的操作占日常操作的比例比极高(50%以上);此外,这种“无元”的文件系统架构对故障的应对不够灵活,服务器进入集群或退出集群都会引起一致性哈希算法的重新计算,从而带来部分数据的迁移,进而影响业务 IO。
近两年来,CephFS 成为开源分布式文件系统的一颗璀璨新星。Ceph 的 RADOS 对象存储层是一个理论完备且实现优秀的系统。CephFS 基于 RADOS,它的元数据和数据都是存储到 Ceph RADOS 之中。Ceph 的哲学是首要确保数据稳定性而轻性能,但现实应用中性能往往也是强需求之一,某些场景甚至要求更看重性能。CephFS 架构上利用了 RADOS,它的 MDS 数据也存储到 RADOS 上,而不是存储到本地硬盘,理论和实现角度上看,这种做法可以复用 RADOS,但也带来了较大的性能衰减。
CephFS MDS 是支持 Active-Active 模式的,MDS 不再是单点,多个 MDS 共同维护一个统一的命名空间。CephFS 实现了它自己提出的动态子树划分算法,其目标是根据文件系统热点情况对 MDS 做动态的压力均衡。不过在大规模生产环境中,这个功能会带来运维的复杂度,因而实际被开启的不多。
人工智能、移动互联时代的一大数据特征,就是海量文件,为了做一个支持百亿级文件的分布式文件系统,我们该如何思考和设计呢?
2 方法论
在确定“方法论”之前,我们要先建立一些原则性认识。
其一是不会有 one size fits all,我们不可能兼顾所有,必须有侧重点,有侧重就会有舍弃。“取舍”,相信是大多分布式开发者的心得。比如分布式系统,我们不可能突破 CAP 理论限制。面对各种各样的业务需求,如果我们只满足 CP,有的业务对 A 有强需求怎么办?如果我们只满足 AP,那相信我们强调数据一致性的存储工程师就不愿意动手,因为我们深知数据稳定是要坚守的底线。因此我们会细化,会支持针对业务的 CA 可以进行一定程度上的配置。
其二是要围绕“主线”去做设计,否则上层的实现会积重难返。我们的核心主线之一就是支持百亿千亿级别文件海量文件。从这个主线出发,我们会去针对性地思考关键问题,去做要点设计。我们都知道,核心设计决定未来。前面讨论到的 MooseFS 和 GlusterFS 等,为我们众多分布式系统研发者提供了学习案例,在它们基础上实现不了百亿级文件,因为已经积重难返。
下面从这两个原则出发,来讨论一下我们设计自己的分布式文件系统时考虑的要点。
3 要点设计
要支持百亿级文件,从前面“方法论”提出的大思路出发,我们认为要实现的关键点有以下几点。
采用中心元数据服务器(即 MDS)
这几乎是必然选择,只有使用了 MDS,CAP 中的 A 才更为可控,系统的整体架构也更加清晰,故障处理更加自如,数据放置策略、故障恢复策略也将更加方便和可控,因为这些行为都在 MDS 控制之下。
我们使用多 MDS 共同组成一个统一的命名空间,为了支持百亿级,对目录树必须做切分。围绕“切分”思路,我们可以做多种切分策略,不同策略有不同的效果。如何做策略就是工程实践问题了,从项目管控以及工程实现的复杂度角度考虑,我们目前实现的策略是按目录哈希切分策略,这已经能满足大多数场景的需求。在未来,我们会再实现其他策略。
MDS 的另一设计要点是,是否使用本地硬盘。产生这点考虑,是借鉴到了 CephFS 的经验,CephFS 复用 RADOS,有好处也有坏处,坏处是性能受到较大影响,好处是工程实践角度更为清晰。我们认为,对元数据的操作要更重视性能,因此我们坚定地选择了 MDS 直接对接本地硬盘。
选择 MDS 使用本地硬盘后,下一个要考虑的要点是,是否直接使用本地 MDS 节点的文件系统,如 ext4 或 xfs。使用本地文件系统,开发和实现会更加高效,,目前我们的选择是直接使用 MDS 的本地文件系统,将来,为了进一步提升 MDS 的操作性能,我们会直接操作裸盘的 KV 系统。
数据存储(即 DSS)要点
DSS 主要思路是 bypass 文件系统,跟 MDS bypass 文件系统类似,这里有两个阶段的考量,第一阶段利用本地文件系统,能快速实现功能。第二阶段是 bypass 文件系统,DSS 直接操作裸盘,即做出一个独立的单机存储引擎,我们的主要考虑点是单机文件系统不利于海量小文件的存储和管理;其次,单机裸盘存储引擎,有助于我们追求更极致的性能,裸盘引擎更利于将来我们对 NVMe 等新型硬件和 SPDK 等新型技术栈做深入整合。目前,我们已经推出了基于裸盘的 DSS 存储引擎。
集群管理要点
分布式集群中,如何对节点是否离线、是否加入等关键事件进行判定,也是要考虑的核心问题之一。我们将这些任务交给集群管理节点,或称为 monitor 来处理。如何实现 monitor 集群,不需要多多考虑,基本上是实现一个 paxos 集群,近几年来用 raft 是一个“流行”趋势。
副本机制和 CAP 开关
副本机制是分布式系统实现数据可靠性的关键思路,它带来的 CA 问题将是面对不同业务时需要考虑的均衡点。如“方法论”所述,我们将 CA 的权衡做成选项,在不同应用场景中可以有不同的侧重。在这个简单思路之上,魔鬼就在复杂的细节里,难点主要在工程实践之中,充足的测试是验证这一机制的方法。
4 “瑞士军刀”式功能开关
要实现百亿级分布式文件存储,以上讨论了我们的出发点和“方法论”的关键要点。基于这些点做出来的系统是“骨架”完整的。
但仍如“方法论”所说,没有 one size fits all 的系统,我们接触的客户需求都是各种各样的,不会一个系统能满足所有业务场景和需求。因而我们的思路是在上面的核心之上,去做丰富的功能,并将主要功能做成开关式控制,某些甚至支持运行时调整。
下面讨论一些主要的功能
分池存储
一个较大规模的分布式集群中,往往会引入不同类型的存储设备。另一方面,用户的多种业务中,往往有关键业务和非关键业务之分。这两个角度,不管从哪个角度来考虑,我们都发现,有将物理资源分池管理的必要性。因此我们实现了对物理资源分池管理的功能,也可称之为分组、分 zone,叫法无所谓,其核心要义是提供物理资源划分的能力。
我们实现了这个机制,目前基于这个机制,我们实现了故障域划分的效果,将资源分配到不同池,实现物理上的故障域划分,减小故障时的影响。
分层存储
有不少业务会存储大量冷数据,对冷数据,往往追求存储成本的节约。如果用户提供了 SSD 和 HDD,并计划将海量的 HDD 空间用作冷存储,用少量的 SSD 空间用作热存储。我们可以将 HDD 空间分成一个池,将 SSD 空间分成一个池,逻辑上将 SSD 池架设到 HDD 池之上,实现一个分层存储的功能,将 SSD 池的冷数据转移到 HDD 池中去。
数据压缩
这个功能需求往往伴随分层存储存在,针对冷数据存储,用户业务往往会再使用我们的数据压缩功能先做数据压缩。
5 后记
本文“囫囵吞枣”般介绍了我们是如何去思考和设计百亿级分布式文件系统的。当前网络资源丰富,开源发达,通过借鉴其他系统的经验,再加上以前的积累,我们对做一个百亿级分布式文件系统形成了自己的理解。简单来说做百亿级分布式文件系统,首先是一个思路问题,其次是也很有挑战的工程实践。本文主要简单地讨论了整体“思路问题”部分,以后有机会我们再一起来讨论小模块的设计细节和实现问题。
版权声明: 本文为 InfoQ 作者【焱融科技】的原创文章。
原文链接:【http://xie.infoq.cn/article/6a8e27982179221e8ffbac489】。文章转载请联系作者。
评论