前言

在上一篇《如何实现反对百亿级文件的分布式文件存储》中,咱们简略“鸟瞰”了实现反对海量文件的分布式文件存储的要害思路,本文咱们开始探讨各个模块的设计思路和局部细节。先从元数据服务开始,元数据服务个别被简称为MDS,示意MetaData Service,或MetaData Server。

MDS数据在磁盘中如何治理

当咱们说要做反对百亿文件的MDS时,咱们要做什么?

咱们先从业务需要说起。绝大多数业务,尤其是传统业务,都是习惯应用文件系统的,因为各种编程语言都提供了丰盛的文件接口SDK,不同的业务依据数据规模应用本地文件系统或NAS。

咱们先以本地文件系统ext4为例,来看一下ext4文件系统的特点。

  1. ext4是针对HDD设计的,基于内核VFS框架。为了实现更好的性能,ext4提供给用户应用的接口个别是buffered IO接口,读写都通过pagecache,写数据并不间接落盘,且元数据(inode)也不间接落盘。更进一步地,ext4应用了journal jbd2,默认模式是ordered,示意仅记录元数据的变动,这个journal也不是实时落盘的。ext4这么做是为了提供更好的IO性能,但在机器掉电时是可能丢数据的
  2. 如下面提到的,ext4是HDD时代的产物,面对SATA SSD甚至是PCIe SSD时力有不逮,施展不出硬件的全副性能
  3. ext4会对硬盘预格式化,格式化后inode数量固定,能反对的文件数量也随之固定。当面对海量小文件场景时,inode率先耗尽,而硬盘理论仍有大量空余空间。
  4. ext4是没有“原子读写机制”的,即如果业务有一个操作,须要read file1, write file2, write file3都胜利才认为胜利,则业务须要本人去做这个组合的原子逻辑,ext4无奈提供现成的回滚机制。

不少分布式文件系统是基于本地文件系统的,它们都将面临以上提及的这些问题。市面上大多分布式文件系统的MDS是基于本地文件系统的,例如ext4。而有的分布式文件系统则间接用本地文件示意业务文件,即用户视角的一个文件,对应MDS ext4里的一个或多个文件,这种形式要面对下面提到的所有问题。还有的分布式文件系统是在ext4之上有本人的封装,比方将文件信息形象为KV,运行时在内存中用std::map之类的数据结构示意,并实现LRU机制,换入换出到底下ext4中,这种形式会面临下面问题的第1、2、4点,同时引入了不少工程复杂度,能够了解为这种形式做到极致就是RocksDB的特定实现。

通过以上剖析,设计MDS时,能够不应用本地文件系统,而是抉择应用RocksDB。大家晓得RocksDB也是基于文件模型的,如果MDS应用RocksDB,但RocksDB应用ext4,那么整个MDS依然会受到ext4带来的性能限度。咱们理解到RocksDB并不强依赖文件系统,因而现实的MDS并不应用ext4,而是间接治理裸盘,并提供一个薄层文件模型去满足RocksDB的运行须要。这块内容较多,咱们在下一篇文章来专门探讨MDS基于裸盘的RocksDB计划的细节。

MDS如何切片

咱们之所以探讨MDS的切片问题,实际上是探讨如何将整个文件系统的元数据通过肯定逻辑搁置在一台或多台MDS节点中。

当应用单台服务器做MDS时,基于裸盘应用RocksDB的计划,相比于间接应用本地文件系统,曾经能治理更多的文件了,但单MDS仍有其限度,比方单MDS反对的文件数量始终存在下限,单MDS对并发申请的解决能力也存在下限。

所以为了设计和实现一个能承载百亿文件的MDS,必然要做元数据切片,应用多台服务器组成MDS集群,每个MDS节点治理局部元数据。

接下来,如何对元数据进行切片就成为外围问题。通过调研和积攒,咱们认为,实践上“动态”切片的办法是不能满足所有场景的需要的。直观上这十分好了解,正如上一篇提到的,咱们做大型零碎面临的都是抉择,不会有银弹式完满解法。这里“动态”切片办法是指不思考动静平衡的切片办法,比方通过哈希将新目录定位到指定MDS节点。

咱们先来探讨切片计划面临的挑战:

挑战1:每个切片的数据量是否平衡?

挑战2:每个切片的IO性能是否平衡?

挑战3:每个切片的访问量是否平衡?

挑战4:如何无效实现range query,如ls等罕用文件系统操作?

对于挑战1,在实践中,咱们认为元数据量是否严格地平衡并不那么重要,咱们只有能做到不要让某个MDS空间被撑爆,而同时其余MDS节点残余大量空间就行。但如果元数据节点的存储空间耗费差距大,可能会影响到MDS的拜访性能,这次要是因为数据量大之后内存LRU的影响和数据索引的影响。

所以,咱们尽量去放弃元数据空间耗费的平衡。但元数据空间耗费是动态变化的,咱们个别会按目录去定位以及分片,比方通过哈希将某个目录定位到指定的某个MDS,目录刚开始为空,但随着时间推移,该目录下的文件会逐渐越写越多。

另一个麻烦的问题是如何解决拜访热点。元数据切片固定之后,可能呈现热点目录刚好都在同一MDS节点的状况,如果某个切片下的某个目录或某些目录被高频拜访,就会造成热点,如果该MDS不能反对这么大的访问量,而其余MDS却非常闲暇,这样既浪费资源,又影响性能。

至于挑战4,ls等操作是用户常见操作,当目录下文件很多时,ls操作耗时会很长,本地文件系统如此,个别分布式文件系统更甚之。如果咱们的切片策略尽量让一个目录的元数据搁置于单个MDS上,那么切片并不会带来更多的ls耗时。

那么现实的分布式文件系统应该采取什么样的元数据分片计划?咱们深刻思考下面的挑战,正如咱们重复提到的一点,大型零碎通常须要在各种问题和挑战之间寻找平衡点,或者做动静的均衡。因而咱们给出的外围设计思路是,给定对立命名空间的目录树,以目录为单位,将目录树拆分到不同MDS上,这样保障了数据本地化。至于拆分时的策略是通过hash,还是通过指定,其实曾经无所谓了,咱们能够采取hash策略,即对于给定目录的元数据,通过hash为其指定一个所属MDS。

对于MDS切片这一主题,Ceph SC04发表的论文”Dynamic Metadata Management for Petabyte-scale File Systems”也做了探讨(关注本公众号,回复“SC04”获取论文),通过浏览这篇论文,并延展浏览它援用的一些论文,咱们发现基于目录树并以目录为根本单位的切片计划,不失为一个直观的、正当的切片计划。这篇论文采取了雷同的思路,但采纳了不同的细节办法,也做了更为谨严的试验和剖析,值得大家去扩大浏览。

当然采纳hash的形式对元数据依照目录进行划分,也不是万能计划,咱们还须要通过其余伎俩去解决这个计划带来的问题:

每个MDS节点优化到极致,使得其可能反对足够多的数据,这样,即便单目录的元数据被hash到某个节点,元数据“动态”划分的计划,仍能反对海量文件。此外,通过对共享读写要害门路的lock critical section的优化,能够反对高并发拜访,从而应答“热点”目录拜访的挑战。这些都依赖于基于裸盘和RocksDB的设计,具体细节咱们将在下一篇探讨。

手动触发的热点迁徙、热点切分机制。反对百亿级别小文件的文件系统设计指标是被海量 (thousands of) 客户端共享拜访的通用型文件系统,个别状况下,不会呈现极其的热点场景,单个目录或几个目录的热点问题,通过单MDS的优化曾经可能解决,但万一某个MDS治理的所有目录都是热点怎么办,咱们须要设计通过命令触发的热点迁徙机制,将热点迁徙到闲暇MDS。另外,如果万一某个MDS治理的所有目录下都有海量文件,那单MDS仍然存在被撑爆的危险,咱们还要设计热点切分机制,将该目录外部划分为多个虚构子目录,将寄存海量文件的目录或热点目录的元数据摊派到其余MDS下来。

MDS多正本机制

下面探讨了MDS设计中最重要的两大部分思路,MDS的数据搁置和治理,以及元数据的切片形式。

除了这两大部分之外,作为一个分布式文件存储,必定还要保证数据的牢靠。咱们应用的也是数据冗余机制,思考到数据特点,咱们举荐2正本,因为这在性能、性能和老本间有一个很好的折中。

应用正本机制有两大思考点,一是正本搁置策略,二是正本间数据一致性。

正本搁置策略方面,联合MDS目录树切片计划,咱们提供的是将MDS节点分组,每组依据正本数设置能够有多台服务器。每组MDS之间做正本冗余。这么做一是满足需要,二是设计和实现简略,三是能够起到物理隔离的作用,单台服务器故障的影响面更小。

正本间数据一致性是分布式畛域常见的问题之一,业界有两大做法,别离是Paxos系和主从复制 (Primary Copy Replication)。Paxos系个别用于低频更新的外围数据的多正本机制,比方在一致性哈希零碎中保护集群视图。MDS多正本这样的场景个别应用的是主从复制,这样既保证了一致性,也能保障肯定的性能。IO先从client发给主MDS,主MDS写本地的同时,再发给从MDS,只有主从MDS都写胜利,才认为本次IO胜利并返回给client。

一样常见地,咱们应用本地journal来保障本地的原子写,应用transaction log来保障故障下的主从复原,同时基于transaction log咱们也不便做主从同步写或是主从异步写的策略。

须要特地提出,相比应用ext4等本地文件系统,基于裸盘治理+RocksDB计划,实现本地journal和transaction log更为不便,效率也更高。

MDS设计要点总结

上一篇《如何实现反对百亿级文件的分布式文件存储》咱们抽象地探讨了设计反对百亿级文件的分布式文件存储的思路,本文咱们探讨了元数据集群MDS三大方面的设计思维:元数据管理计划、元数据切分计划和多正本机制。下一篇咱们将探讨本地裸盘治理+RocksDB计划的设计和实现细节,后续咱们还将一直地做其余组件的设计思路、计划和实现方面的探讨。

当然,文字表白不如当面探讨直观,文章再具体,也总会漏掉不少信息。咱们次要探讨外围思路和模块,外部的各个小方面的实现抉择和细节,不同实现都会有很多出彩之处,但出于篇幅和宗旨,在文章里,咱们就疏忽了。咱们十分欢送有趣味的敌人们留言探讨,也十分欢送有趣味的敌人们来实高空基,更是十分欢送有趣味的敌人们退出咱们,一起去探讨、抉择和实现更好的计划、更好的代码。

咱们下一篇见。