摘要
我们开发了 Ceph,一种分布式文件系统。该文件系统提供极佳的性能,可靠性以及扩展性。通过专为不可靠的对象存储设备(Object Storage Device,OSDs)所组成的异构、动态集群而设计的准随机数据分配算法(CRUSH),利用其替代文件分配表,Ceph 将数据与元数据进行了最大程度地分离。通过将数据分布,失效检测恢复指定给运行特殊本地对象文件系统的半自动化的OSDs的方式来使设备具备智能性。而动态的分布式元数据集群,为各种通用目以及科学计算文件系统工作负载提供了无逢自适应,且高效的元数据管理。经测评,在各种工作负载中,Ceph 都表现出了相当出色的 I/O 性能以及可扩展元数据管理,并且支持多达每秒250,000次的元数据操作。
1 介绍
在各种应用中,文件系统的总体性能都是非常关键的。因此长期以来,系统设计者一直在竭力寻求提高文件系统性的方法。分布式文件系统的性能以及扩展性一直受到科学与高性能计算的驱动,而最近这几年,通用目的的系统也要求文件系统的具备高性能与扩展性。传统的解决方案,像 NFS 提供一种直接的模式,即服务器输出一个文件系统,客户端即可将其目录结构影射到本地文件系统中。虽然使用广泛,但是这种集中式的C/S结构对于性能的提高是一个巨大的障碍。
许多最近的分布式文件系统都采用基于对象文件的系统架构,在这个构架下传统的磁盘由 OSDs 替换。一个 OSD 是由 CPU、网络接口、本地磁盘或者 RAID 所组成。比之于传统磁盘,在 OSDs 上,客户端可以读写字节数大得多有名对象(通常大小是不固定的),并且将底层数据分配责任分发给设备自己(OSD)。典型地,客户端只与元数据服务器交互(MDs)来执行元数据操作,直接与 OSDs 通信来执行文件的 I/O,通过这样方式显著地提高了系统的可扩展性。但是这种模式还会受到扩展性的限制,因为元数据负载要么很少甚至不是分布的。传统文件系统规范,如分配列表、inode 表以及代理 OSDs 本身的责任,会进一步限制可扩展性与性能,并且增加可靠性维护的代价。
我们引入 Ceph 这样的分布式文件系统,其能提供极佳的性能、可靠性,同时又有无可比拟的可扩展性。我们的构架设计是基于在 PB 级别的系统客户所具有的动态特性假设,即大系统总是增量搭建的,并且结点的失效是常规事件而不是异常事件,负载量与负载特点总是随时间不断变化。
Ceph 通过用产生函数来替换文件分配表的方式,将数据与元数据操作解藕。这使得 Ceph 能够使 OSDs 具备智能性,因此可以将访问数据、更新序列化、复制及可靠性,失效检测与恢复等的复杂性分散到 OSDs 设备上。利用高度可配接的分布式元数据集群架构极大地提高了元数据访问的可扩展性,并借此提高了整个系统的可扩展性。我们探讨推进我们在系统构架设计之初的目标与负载特性的讨论、分析它们对于系统及性能的影响,并结合我们的经验,从而来实现功能系统的原型。
图 1:系统构架。客户端与OSD直接通信并执行文件I/O。每个进程都可以直接与客户端实例连接,或者与已经挂载的文件系统进行交互。
2 系统概述
Ceph 有三个主要组件:客户端,用于向进程及主机暴露一个“类-Posix”文件系统接口;一组 OSDs,用来收集并存储所有的数据以及元数据;元数据服务器集群,来用管理名字空间(文件名以及目录),并处理安全,一致性以及相关性(见图1)。我们说 Ceph 是“类-Posix”是因为,为了符合应用要求并提高系统性能,我们扩展了接口,并且有选择地放宽了一致性语义。
Ceph架构的主要目标是可扩展性(即能扩展到数百Petabytes 或者更多)以及性能与可靠性。扩展性可从多个维度来考虑,包括全局存储能力以及系统的吞吐量,以及单个客户端、目录、文件的性能。我们的目标负载包括这样的极端场景:即成百上千个主机同时并发读写相同文件,或者在同一个目录创建文件。此类场景在超级计算集群的科学应用中相当普遍,并且在未来的通用目的的工作负载中也有出现的迹象。更重要的是,我们认识到分布式文件系统的负载是动态的,因为做为活跃应用,对于数据与元数据的访问以及数据集本身都是随时间不断变化的。Ceph 通过三个方面的特性设计,在直接解决了扩展性的同时,取得了高性能、可扩展性及可用性。这三个特性为解藕数据与元数据的访问,动态分布式元数据管理,以及可靠的自动分布式对象存储。
解藕数据以及元数据——Ceph 最大化地分离了与文件数据存储与元数据管理。元数据操作(打开,改名等)统一地由元数据集群服务器管理,而客户端则直接与 ODSs 通信来执行文件的 I/O(读与写)。因为代理了底层块设备的分配决策,因此基于对象的文件系统能够提高文件系统的可扩展性。但是另一方面,现有的基于对像的文件系统[4,7,8,32]只是通过将长的单文件分配块列表替换为短的分配块列表。而 Ceph 则是完全取消了分配列表。另外,文件数据利用专有数据分配函数,被分片到可计算的具名对象后存储到存储设备上。这使得任何部分都可以通过计算(而不是查找)得到文件名以及组成文件的对象的位置,而不是需要维护文件对象的列表,简化了系统的设计,减少了集群服务器的负载。
动态分布式元数据管理——由于文件系统的元数据操作基本占了文件系统负载一半,因此有效的元数据管理是整体文件系统的关键。Ceph 利用创新的元数据管理,即“动态子树分区”,使得元数据的管理具有适配性与智能性,因为元数据集群可将文件系统的目录层级的管理责任在上百个 MDSs 之间进行分配。(动态的)层级式分区在每个 MDS 的负载上保留了本地性的同时,利用有效的更新与合并预取来提高一般负载的性能。更加重要的是,元数据的负载是根据当前访问模式来在元数据服务器之间进行分配的,使得 Ceph 能够有效利用可得的 MDS 资源,并在任何负载下取得近线性的 MDSs 服务器的扩展性能。
可靠的自动化分布式对象存储——大型系统由数以千计的设备组成,天生就具有动态性:它们是增量构建的,并随着部署新设备或者清除老设备时增长或者收缩,可以预见集群中的设备会频繁失效,同时会有大容量的数据被创建、移动、删除。所有这因素都要求数据的分布要有效利用可得的资源,并且保持某个等级的复本。Ceph代理存储数据的 OSDs 集群中,数据迁移、复制、失效检测及恢复的职责,并且在高的层级上,向客户端以及元数据服务器提供一个单一的逻辑对象存储。这种方式使得 Ceph 可以有效平衡每个OSD的智能性(CPU以及Memory),以此来取得可靠的,高可用的对象存储,并且具备线性扩展的能力。我们将描述 Ceph 客户端、元数据服务器集群的操作,分存式对象存储,以及它们受架构特性的影响,我们也将描述原型系统的状态。
3 客户端操作
通过描述 Ceph 客户端操作我们介绍了 Ceph 各组件的操作流程,以及他们与应用的交互过程。Ceph客户端在每个执行用户代码的主机上执行,并向用户代码暴露文件系统接口。在 Ceph 的原型中,客户代码完全运行在用户态,可以直接连接到客户端,或者通过FUSE[25](一种用户态文件系统接口)挂载的文件系统来访问。每个客户端维护自己的文件数据 Cache,独立于内核页以及buffer caches,使得直接连接到客户端的应用能够访问到。
3.1 文件I/O 及其权能
当进程打开一个文件,客户端发送一个请求到MDS 集群,某个 MDS 则遍历文件系统树,并将文件名转换为 inode,在这个 inode 中包含一个唯一的 inode 号,文件所有者,模式,大小以及其他单个文件的元数据。如果文件存在,则访问被允许,MDS 则返回 inode 号,文件大小,以及用于影射文件数据到存储对象的分块策略。同时,MDS 也返回客户端的权能(如果有),用于表示客户端可以执行的操作。权能当前包括4位,用来控制客户端是否能够读、cache 读、写、buffer 写。未来,权能将包括安全键,这样使客户端对于 OSDs 的读写是经过授权的[13,19] (当前的原型是对所有的客户端都授权)。其他的 MDSs 对于文件I/O只限于管理权能,以保证文件的一致性与文档正确的语义。
Ceph 通过一系列的分块策略将文件影射到连续的对象。为避免使用文件分配的元数据产生,对象名字仅是 inode 号与分块号。对象复本然后通过 CRUSH 算法被分配到 OSDs 中,这是一个全局范围的映射函数(将在 5.1 节说明)。例如,如果一个或者多个客户端打开文件用于读访问,某个 MDS 将授权这些客户端以读,并且缓存文件内容的权限。通过 inode 号、布局、文件大小,客户端就能够命名并定位所有包含文件内容的对象,然后直接从 OSDs 集群中读取。任何不存在的对象或者字节区都定义为文件的“洞”,或者数据“0”。相似的,如果一个客户端打开一个文件写,它就被授权对文件进行写或者缓存写的权限,其在文件任何位置产生的字节都将简单地写到对应的 OSD 中的对应对象。客户端在文件关闭时放弃所有的权限,然后向 MDS 提供文件的大小(即最大的写偏移),这些文件大小重新定义了包含数据文件的对象(可能存在)集。
3.2 客户端同步
POSIX 语义要求读要反映任何之前写入的数据,并且写是原子性的(对于交叉并发写能够有一定的并发顺序)。当一个文件被多个客户端打开写,或者混合读写,MDS 应该撤销任何读Cache写缓存写的权能,强制客户端I/O对该文件进行同步。也就是,每个应用的读与写都应该在 OSD 确认之前阻塞,从而将更新序列化与同步的负担指派给了存储每个对象的 OSD 上。当写跨越了对象的边界,客户端需要受影响的对象的互斥锁(由相应的 OSDs 授权),并且立即提交写操作,然后释放锁,以求取得需要的序列顺序。对象锁也同样用于覆盖大的写操作延迟,通过获取这个锁,然后将数据进行异步刷出。
不用惊讶,同步 I/O 会导致应用的性能下降,尤其是对于小的读写操作,这是因为延迟惩罚——至少要执行一轮到OSD的操作。(我想意思是数据从发起读写到完成算一个 round-trip,这样如果太多小的读写操作,一个 round-trip 所产生的延迟累积起来就很可观了。)尽管在通用负载中读与写共享相对较少,但是这样的场景中性能却是一个关键参数。正是因为这个原因,在应用不依赖于数据的一致性的情况下,放松了对一致性的要求,但要付出与标准不一致的代价。
虽然通过全局切换,Ceph 缓解了这样的问题,但是许多其他的分布式文件系统却对此不太关注 [20],这是个不太讲究,因此也不让人满意的解决方案,因为要么牺牲系统的性能,要么缺失系统层面的一致性。正是因为这个原因,高性能计算社区针对 POSIX 的接口提出了许多高性能计算的扩展,Ceph 实现了其中的一个子集。一个显著的一个例子就是,加入了 O_LAZY 这样的标志位用来缓解打开那些允许应用显式并发共享写的所产生的一致性问题。对于有性能要求的应用,它们会自己处理自己的一致性问题(例如在 HPC 负载中通过向文件的不同位置写[27]),这样就可以允许缓存读定,其他的情况下就要进行同步读写。如果需要,应用也可以通过两个调用来执行显式的同步:lazyio 会将某个范围的字节刷到对象存储中,并且保证之前的操作能够反映在后续的读操作中。通过在客户端之间通过同步的 I/O 这样的模式来提供正确的读写与共享写语义,以此来保证 Ceph 简洁性,同时扩展了应用的接口,缓解了关注性能的分布式应用程序对于一致性的要求。
3.3 名字空间操作
客户端与文件系统名字空间之间的交互操作是由元数据服务器集群来管理的。读操作(如 readdir,stat)以及更新操作(如 unlink,chmod)都是被 MDS 同步应用的,以此保证串行性,一致性以及正确的安全性与数据安全。为了简单起见,没有元数据锁或者租期锁分配给客户端。特别是,对于 HPC 这样的负载,回调则可能会以复杂性的增加这样的代价,换取一丁点好处。而 Ceph 对于大多数的元数据访问场景都进行了优化。对 readdir 之后的每个文件执行 stat 操作(如 ls -l)就是极为普通的访问模式,会对巨型目录的访问性能带来巨大的伤害。在 Ceph 中,readdir 操作只需要向 MDS 发送一个请求就可以取得整个目录内容,包括 inode 内容。在默认情况下,如果 readdir 之后紧跟着一个或者多个 stat 操作,其仅仅是将简略的缓存的信息返回而已,其他情况,信息则会被丢弃。尽管这仅仅是稍微缓解了未留意的 inode 交叉修改所带来的相关性,我们为了性能的提升也非常愿意做这样的取舍。这样的行为可以通过 readdirplus 的扩展来捕获,这个接口返回的是目录项的 lstat 的结果(就像某些特定的 OS 所实现的 getdir 所执行的操作)。
Ceph 通过将元数据缓存保持得更久一些,就可以将一致性问题进一步缓解,这正如早期的 NFS 版本所做的,NFS 在早期缓存的时间典型为30秒。然而,这种方式往往打破了对于应用来讲是最关键相关性,例如那些使用 stat 来确定文件是否已经更新的操作——在这样的情况下,它们要么行为不正确,要么需要等待旧的Cache数据超时。我们偏向于为提供正确的行为,扩展那些影响了性能的接口。这个选择可以通过有多个客户端打开写的文件执行 stat 操作来说明。为了返回正确的文件大小以及修改时间,MDS 会取消所有的写权限,并临时停止更新并向所有的写者收集最新的大小以及 mtime(修改时间)值。将且将最大的值做为 stat 的返回。此后,相应的写权能重新恢复使客户端可以进一步的操作。看起来,停止所有的写操作有点过于极端,但是为了保护序列化的正确性却是必要的。(对于单个写者,正确的值可以从写客户端获取而不需要停顿)对于不需要相关性的应用——POSIX 接口没有专门针对它们的需求来编写而使其受到一定的伤害——可以使用 statlite[31] 接口来获取文件的信息,该接口利用位屏蔽来指定 inode 的哪些域不需要相关性。
4 动态分布式元数据
元数据操作一般占文件系统负载的一半左右[22],并且处于操作的关键路径上,因此 MDS 集群对于整体性能非常关键。在分布文件系统中,元数据的管理也是一个扩展性挑战:尽管容量以及集合 IO 率几乎可以通过添加更多的存储设备来任意扩展,但是元数据操作会包含更多的交叉依赖,使得扩展的一致性与相关性管理变得相当困难。
在 Ceph 中,文件与目录的元数据是非常小的,其由整个目录(文件名)以及inode (80字节)组成。不像传统的文件系统,Ceph 不需要文件分配元数据,对象名由 inode 号组成,数据在 OSDs 上的分布则通过 CRUSH 算法实现。这简化元数据负载,使得 MDS 能够有效地管理非常巨大的文件集合,而不管文件大小。我们通过两层存储设计还进一步减少元数据与磁盘相关的 IO,使元数据的本地化最大化,并利用 DSP[30](动态子树分区)来有效地进行缓存。
4.1 元数据存储
尽量 MDS 集群的目标在于通过内存缓存来满足大部份的请求,但是元数据的更新却必须安全地提交到磁盘。集合性的,打包方式,并延迟刷出日志操作,使得每个 MDS 能够以一种高效分布式的方式,快速地流化其更新的元数据到 OSD 集群中。单 MDS的日志,每个达数百兆字节,同时合并重复的元数据更新(对于大多数负载来讲很常见),因此当旧的日志记录最后刷出到持久化存储时,许多的信息已经过期了。
尽管 MDS 的恢复在我们的原型中还没有实现,但是日志的设计使得在MDS 失效时,另一个节点能够快速扫描日志来恢复失效节点内存中缓存中的关键内容(为了快速启动),通过这样来恢复文件系统状态。这样的策略提供了两最好的实现方案:高效地将更新流化更新到磁盘(顺序地),极大地压缩了重写负载,使得长期存储布局能够为未来的读访问进行优化。特别地,结点(inode)内嵌在目录里,使得 MDS 通过一次对 OSD 的读就可以将整个目录进行预取,并且在负载的多数情况下都是读取的本地的数据。将目录内容写到 OSD 集群中,使用的都是与日志元数据以及文件相同的分块以及分布策略。inode 被分配到一系列的元数据服务器中,并在我们的原型中被认为是不变的,尽管未来它们可能在文件删除时需要收回。任意的某个定位表(anchor table)[28]保存一些 inode,它有多个硬连接,并能通过 inode 号进行全局寻址——所有的 inode 所产生的代价不会比普通的单连接的,同时拥有大量稀疏空间, 繁杂 inode 表更多。
图 2:Ceph 根据当前的负载情况动态地将目录层次结构影射到元数据服务器上。单个目录只有它在成为热点的时候才会被哈希到不同的结点上。
4.2 动态子树分区
我们的主复本缓存策略,让一个授权的MDS 负责管理所有元数据的缓存的关联性,以及串化更新。大多已存在的分布式文件系统利用某种静态的基于树的分区来表示这种授权(通过要求管理员将数据集切割成更小的静态“卷”),当前的一些实验性的文件系统已经采用哈希函数来分布目录以及文件元数据[4],但却为了负载的分期牺牲了数据的本地性。两种方式都有关键的限制:静态子树分区无法处理动态负载以及数据集,而哈希则破坏了元数据的本地性,而本地性是高效存储与预取元数据的关键。
Ceph MDS 集群基于动态了树分区策略[30],通过适配,将元数据层级在结点集之间进行分布,如图2所示。每个 MDS 利用指数化延迟的计数器评估目录层次中的元数据的热度(poularity)。每个操作都递增受影响的 inode 的计数器,以及所有它祖先结点,直到根目录结点。通过这样的方式向 MDS 提供了一种带权重的负载分布情况。MDS 的负载值会定时比较,适当的分区大小会被迁移,来保证负载最终是分散的。长期存储的组合并辅以仔细构造名字空间锁,使得这样的迁移只需要处理内存中的缓存并赋予相应的权限即可,从而最小化对关联锁以及客户端权能的影响。
输入的元数据,为安全起见被写到新的MDS 的日志中,而两结点中其他的日志记录项则用于保证结点失效时,通过授权的转移来解决(类似于两阶段提交)。最终的结果是,基于子树的分区总是进行最小前缀的复制,同时又保证了本地性。当元数据在多个 MDS 之间复制时,inode 的内容被分成三组,每个都有不同的一致性语义,这包括:安全(所有者,模式等),file(大小,修改时间)以及不可变性(inode 号,创建时间,布局等)。不可变域不会改变,安全与文件锁由独立的有限状态机来管理,每个都有不同的状态集,传输的设计符合不同的访问模式与更新模式,同时最小化加锁的内容。例如,所有者及模式(mode)在遍历路径上需要安全检查,但是很少改变,因此需要较少的状态,而文件锁反映了更广范围的客户端操作模式,例如通过控制 MDS 的权能来实现客户端的权能。
4.3 流量控制
对目录层级在多个结点之间分区,能够平衡很多负载类型,但是并非总是能够处理热点阻塞与缓存拥挤,即如很多的客户端同时访问同一个目录或者文件。Ceph 利用对于元数据的热度的知识,来为热点在需要时提供一种更宽的热点分布,这在多数据情况下不会导致相关的负担以及目录的本地性的损失。内容被重度访问的目录(如许多打开操作)将有选择性地在多个结点复制以分散其负载。对于大型目录或者正在经历重度写负载的情况(如创建大量文件),则将他们的内容通过文件名的哈希在集群之间分布,在分布平衡的同时,带来的代价就是本地性的损失。
这种适配方式,允许 Ceph 采用各种粒度的分区大小,使其在特定场景以及某些文件系统部分,有效地利用各种粗细的分区粒度。每个 MDS 都向客户端提供关于授权以及相关 inode 结点及其祖先结点的复本的更新信息,这样客户端能了解与其交互的文件系统部分元数据分区。未来的元数据操作将直接授权(针对更新)或者根据已给的路径的最深前缀来随机生成复本(针对读)。通常情况下,客户端能够了解到不常用元数据的位置(未复制的),这样能够直接与对应的 MDS 进行交互。客户端访问热的元数据时被告知,元数据要么在不同的 MDS,或者多个 MDS 上,这样将客户端绑定,使特定的元数据块在特定的 MDS 上,从而使热点与缓存拥挤出现之前就消除了。
5 分布式对象存储
从高层看,Ceph 的客户端以及元数据服务器将对象存储集群(可能包含数以千计的OSDs)看成一个单独的逻辑存储空间。Ceph 的可靠的自动分布对象存储(RADOS,Reliable Autonomic Distributed Object Store)在集群中通过代理对象复制的管理,集群的扩展,以及对 OSDs 失效检测与恢复来获取线性的容量与性能的扩展能力。
图 3:文件被分块成许多对象,并且组成 PG(定位组),并利用 CRUSH,一种特定的复本定位函数,向 OSDs 中进行分发
5.1 利用 CRUSH 进行数据分发
Ceph 必须将 Petabytes 级别的数据分布到不断演进的,具有成千上万个存储设备的集群中,这样设备的存储与带宽才能够被有效利用。为了防止不平衡(例如最近安装的设备可能总是空闲)或者负载不对称(如热数据总是在新设备上),我们引入将新数据随机分配的策略,将已经存在的数据随机迁移到新的设备中,并且统一地将已经移除的设备进行上的数据进行重新分配。这种随机的方法是可靠的,因此在不同的负载下都可以很好地运行。
Ceph 首先利用简单哈希函数将对象影射到定位组(PGs),此函数利用可调整的位屏蔽来控制 PG 的数量。我们选择每个 OSD 约 100 个 PGs 来平衡 OSD 的使用,这些 OSD 维护大量相关的元数据相关的复本。然后通过 CRUSH (可扩展哈希下的可控的复本)[29]将 PG 指定给 OSD。这是一种准随机的数据分布函数,能够有将地将 PGs 指定给有序的 OSD 列表,利用这些 OSD 来存储复本。这不同于传统的方法(包括其他基于对象的文件系统),这些方法中的数据存储不依赖任何块以及对象元数据列表。为了定位任何对象,CRUSH 需要的仅是 PG,以及 OSD 集群的影射:即一个压缩的,组成集群的层次描述的设备。这种方法有两个好处:一是它是完全分布的,因此任何部分(客户端,OSD,MDS)都可以独立地计算任何对象的位置。第二,这种影射不会变动频繁,因此基于分布式的元数据交换就没有了。通过这样的方式,CRUSH 同时解了数据分布问题(数据存在哪的问题)以及数据位置的问题(我把数据存在哪了的问题)。通过设计,对存储集群的小改变,不会对于已经存在的 PG 影射造成很大的影响,因此最小化了在设备失效或者扩展情况下的数据迁移。
集群的影射层级结构被构造成与所在集群的物理或者逻辑结构,以及可能的失效源进行对齐。例如,一个完配 OSD 的设备可能有 4 级层级,装满机架的 OSDs,以有机架上的所有背板,以及背板中所有的行。每个 OSD 都有一个权重,用来控制可被赋予的相对数据量。CRUSH 根据定位规则将 PG 影射到 OSDs,这些规则定义了一定的复本等级以及对定位的限制性条件。例如,将每个 PG 都复制到3个OSDs 上,并且都位于在同一行(为防止行之间的复制数据产生的流量),但是分布在不同的背板中(为了最小化电源失效以及交换机失效的带来的影响)。集群影射同时也包括失效或者非活动设备的列表,以及一个时期数据,当影射变化时,这个时期数据就会递增。所有的 OSD 请求都被打上标签,其中包括客户端的影射时期。这样所有部分都可以对当前数据的分布情况取得一致。递增影射的更新在关联的 OSDs 之间的共享,如果客户端的数据已经过时,那么它就会注入 OSD 回复。
5.2 复制
与 Lustre[4]这样的系统比较起来,Lustre 假设某个设备通过类似于 RAID或者故障切换的 SAN 即可构造足够可靠的 OSDs,而 Ceph 则假设在 Petabytes 或者 Exabytes 级别的系统中,设备失效是很平常的事情。在任何时间点,可能有多个OSDs 是不可操作的。在可扩展的情形下,为了保证系统的可用性以及数据的安全,RADOS 通过可变的主复本复制技术来管理自己的数据复本,同时利用多个步骤来保证对性能的影响最小化。
数据是根据 PGs 来复制的,每个 PG 都影射到一个有序 n 路 OSD中(对于 n 路复制)。客户端将所有的写发送到第一个未失效的 OSD 的对象 PG 中(主),然后赋给对象以及 PG 一个版本号,然后将写转发到所有其他复本 OSDs 中。当所有的复本都已经应用并且更新回得到了主复本,则主复本在本地应用更新,然后将写确认发送到客户端。读则将被定向到主复本。这样的方式使用客户端不要关心数据在不同版本之间序列化以及同步的复杂性,这些复杂性会在其他的写者到来或者失效恢复情况下更加严重。同时,这也将由复本所消耗的带宽由客户端移到了 OSD 集群的内部网络,这样我们可以期望整个资源的最大可用性。复本之间的失效被忽略了,后续的恢复(请看5.5节)将可靠地恢复数据的一致性。图 4:RADOS 当写已经应用到了所有的复制对象 OSDs 中的缓存中返回一个 ack 确认信息。只有当信息提交到了磁盘才会发送一个最终的 commit 通知给客户端。
5.3 数据安全
在分布式存储系统中,有两个原因使得数据要写到共享的存储上。首先,首先客户端希望自己的变更能够让其他的客户端感知,并且要迅速:即写操作应该尽可能快地对其他客户端可见,特别是多个写者,或者读者写者混合迫使客户端执行同步操作。其次,客户端也想知道他们所写的数据已经安全地进行了复制到磁盘上了,因此在设备失效时也能够留存下来。当通知更新时,RADOS 将同步与安全分离,使得 Ceph 实现低延迟更新与高效的应用同步,以及定义良好的数据安全语义。图4 解释了信息在对象写的时候的发送情况。主对象将更新发送给复本,然后当这些数据到达 OSD 的内存缓存(buffer)后发送 确认ack) 消息,这样同步的 POSIX 接口就可以返回到客户端了。终极提交可能要等到几秒钟之后数据完全写到了磁盘。当更新完全进行了复制,并且可以有效地容忍单个 OSD 失效时,我们就发送 提交(commit) 消息给客户端,尽管这会导致客户端延迟的增加。在默认状态下,客户端也会对写操作进行缓存,直到它们将其提交以避免在 PG 中的所有 OSD 同时掉电而导致的数据丢失。当从这种失效状态中恢复时,RADOS 在接受任何新的更新时,以固定间隔重新执行之前已经确认的更新。
5.4 失效检测
及时失效检测对于维护数据的安全是非常关键的,但是当集群的规模扩张到数据以千计的设备后,这样的检测就变得相当困难了。对某种失效,例如磁盘错误或者数据崩溃,OSDs 自己就可以上报。但是例如使得 OSD 不可用的问题,如网络,RADOS 使每 PG 中的每个 OSD 检测同一个 PG 中的其他 OSD,来实现一种主动的检测。在大多数情况下,可以利用已经存在的复制流来作为活性检测的机制,因此没有什么额外的负荷。如果某个 OSD 没有从其他对端中收到信息,就会显式地发送一个 ping。RADOS 会考虑两个维度的活性:一是 OSD 的可达到性,以及是否被 CRUSH 分配数据。某个没有反应的 OSD 将被标记成 Down,任何主复本都将其职责(即更新序列化,复制)临时地传递给同一个PG 中的其他 OSD。如果 OSD 没有快速地恢复,则其就会被标记成不在数据定位组中,则其 PG 中的其他 OSD 则加入,并且将失效的 OSD 的内容复制过来。在失效 OSD 上已经挂起的操作只需要向新的主复本重新提交即可。有大量的网络问题都可以导致 OSD 的连接性出现时断时续,一个小的集群监控将收集失效报告,将把间歇性的或者系统性问题(如网络分离)集中过滤。监控器(当前只实现部分)使用选举,主动端点监控,短期租赁以及两阶段提交来共同提交集群影射的一致性以及可访问性。当影射更新并反映了失效以及恢复情况,受影响的 OSDs 将会增量更新其影射,然后利用已经存在的 OSD 之间的通信流来在集群中间进行分发。分布检测使得 Ceph 不用增加过度的监控负担就可以实现快速的检测,同时又利用集中仲裁机制解决了数据不一致性问题的出现。最重要的是,RADOS 针对 OSD 中标志为 Down,但是没有标记成 Out 状态的OSD不进行初始数据的复制(例如当一半的 OSDs 都掉电后的情况)。
5.5 恢复及集群更新
由于 OSD 的失效,恢复以及部署新存储设备,OSD 集群影射是会变化的。Ceph 对这些变化的处理方式都是一样的。为了快速恢复,OSDs对每一个 PG 的每一个对象以及最新的更新日志(名字以及更新版本,或者删除的对象)都维护了一个版本号。当活动的 OSD 收到更新影射的消息,它将遍历所有的存储在本地的 PG,并计算 CRUSH 影射来确定其对哪一个负责,是作为主还是做复本。如果 PG 的成员有了变化,或者 OSD 刚刚启动,那个这个 OSD 必须与 PG 中的其他 OSD 建立连接端点。对于作为复本的 PGs,OSD 向主复本提供当前PG 的版本号。如果主复本没有最近的 PG 状态,为了确定正确 PG 的正确内容(最近的)则从当前的或者前一个 PG 的 OSD 中取得 PG 变更的日志(如果必要的话,也取得完整的内容)。主复本将数据的增量更新日志(如果必要,连同完整的内容)发送给其他的复本设备,这样每一部份都将取得 PG 的内容,就算它们本地的内容是有差异的。只有在主复本确认的正确的 PG 状态,并且将其共享给了其他的复本设备后,针对 PG 中对象的 IO才会被放行。之后,OSDs 将独立负责从其他对端中取回丢失的数据以及更新过时的数据。如果某个 OSD 收到一个空白或者丢失的对象的请求,则会延迟处理,并将这个对像的恢复移动到处理队列的前部。例如,如果 osd1 崩溃了,并且被标记为 Down 状态,osd2 成为 pgA 的主复本。这时如果 osd1 恢复了,在启动后它会请求最新的影射信息,监控器也将其标记为启动状态。当 osd2 收到了最终的更新信息,则它会意识到自己不再是 pgA 的主复本,并发送 pgA 版本号到 osd1。此时 osd1 将从 osd2 中取回 pgA 最新的更新日志记录,并告诉 osd2 它的内容才是最新的,当所有对象的恢复完成后,osd1 才会处理其他的请求。
由于失效恢复完全由个个的 OSDs 来驱动,每个受失效 OSD 影响的 PG 对于替换的OSD 来讲都是并行恢复。这种基于FaRM(Fast Revovery Mechanism) 的方式,减少了恢复的时间,提高了数据的整体安全性。
5.6 使用 EBOFS 的对象存储系统
尽管许多的分布式文件系统都使用像 ext3 这样的文件系统来管理底层存储[4,12],但是我们发现这些接口的性能对于对象存储负载来说有点差[27]。已经存在的 Kernel 接口对于限制了我们正确理解对象安全地存储到磁盘的能力。同步写或者日志机制提了供相应的安全机制,但是需要要忍受较大的延迟以及性能损失。更重要的是,POSIX 接口无法支持对于元数据更新操作的原子性(例如属性更新),而这对于管理 RADOS 的一致性是非常重要的。因此,Ceph 利用 EBOFS,即“扩展的基于B树的对象文件系统(Extent and B-tree base Ojbect File System)”来管理本地的对象存储。通过在用户态实现这样的文件系统,并直接与底层块设备进行交换,可以使我们定义自己的底层对象存储接口以及更新语义,这样的更新将更新序列化(为了同步)与磁盘提交进行分离(为了安装)。EBOFS 支持原子事务(例如,对多个对象的写属性更新),当在内存中的缓存更新之后才会返回,同时提供异步的提交确认。在用户态实现,除了能够提供更大的灵活 性以及实现更容易外,也避免了繁琐的与LinuxVFS以及页缓存(page cache)的交换,这两者的设计都基于不同的接口与负载类型。而大多数的 Linux 文件系统会延迟一段时间之后才会更新,而 EBOFS 则合并磁盘的写,并侧向于在连续的更新 I/O 操作中取消挂起,因为连续更新中的 I/O 挂起是多余的。这些都给我们提供了针对底层磁盘更长的 I/O 队列以及提高了相应的 I/O 调度效率。
用户态的调度器也使得最终的优先负载的调控更加容易(如针对客户端的I/O与恢复I/O),或者说提供了一种服务保证机制。EBOFS的设计核心是可靠,灵活以及完全与 B 树整合,这样可以来定位对象在磁盘中的位置,管理块的分配与索引收集(PG),块的分配是根据数据维度(开始与长度)来执行的,而不是块列表,这样可以使得元数据更小,也能够使 EBOFS 更快地定位至下一个写位置或者在数据相关的位置找到空闲空间,从而限制长期的碎片。唯一的例外是针对每个对象的块分配信息,所有的元数据都保存在内存中,这样即简化了操作也提高了性能(即使针对大卷,元数据也非常小)。最后,EBOFS 合并执行 Copy-On-Write:除了超级块的更新,数据总是写到一个磁盘未分配的块位置。
6 性能与扩展性评估
我们将原型在不同的测评环境中进行测试,证明了Ceph 的可靠性,性能及可扩展性。在所有的测试中, OSDs 以及 MDs 都是用户进程,并运行在双核 Linux 集群系统上,系统中采用的是 SCSI 磁盘,利用 TCP 来进行通信。总的来说,每个 OSD 或者 MDS 都运行在本主机上,而其他的数以千计的客户端实例则可能在产生负载的时候共享一个主机。
6.1 数据性能
EBOFS 提供极佳的性能以及安全语义,同时,使用 CRUSH 以及代理复制与失效、恢复操作使得数据分布平衡,这使得整体的 IO 系统随着 OSD 集群的扩展而增加。
6.1.1 OSD 吞吐量
我们测试了14个结点的 OSD 集群的IO性能。图5 显示了每个 OSD 的在不同的写大小与不同复本数下的吞吐量。负载则通过其他 20 个结点的 400 个客户端来产生。性能主要受裸磁盘的 IO 性能限制(大概58MB/S),并在横轴上显示。复本数据产生了两倍及三倍的磁盘 IO,当 OSD 数固定的时候,导致相应的客户端的性能降低。图6 显示的是,通过与 Ceph 一样的负载比较了 EBOFS 与通用文件系统的性能(ext3,ReiserFS,XFS)差异。客户端同步写大文件,并被分割成 16MB的对象,然后再将其读回。尽管 EBOFS 在小的读写性能上由于线程与锁的原因有下降(比起传统文件系统),当 EBOFS 以大于32KB的方式写时,其性能跟磁盘的饱和性能接近,而读时,则因为数据在磁盘上存储与我们写的方式匹配,就算当它们非常大的时候,因此其性能也显著超过它们。性能的测试使用的是干净的文件系统。正如之前的设计所揭示的,EBOFS 的文件碎片率要远低于 ext3 文件系统,但是我们也没有测试其他旧的文件系统的表现。无论在什么情形下,我们预期 EBOFS 的性能在文件系统使用很久之后不会表现得比这些文件系统差。图5:单 OSD 写性能。横轴表示的是物理磁盘的上限。复本对于 OSD 的吞吐量的影响非常小,就算 ODSs 的数量是固定的。n-路 复本缩小了整体n的因子的有效吞吐量,因此复本数据必需写到 OSDs 中。
图6: EBOFS 与通用文件系统的性能比较。尽管小的写由于我们的粗锁的影响而导致写性能的下降,但是当写大小大于 32KB 时 EBOFS 可能取得裸盘的饱和性能。因为 EBOFS 在大增量写时,将数据以大连续块方式写入,因此它具有明显的读性能提升。
图7:在不同写大小以及复本数下的写延迟。多于两个复本的情况下,在小块写时的代价很小,因为复本的更新是同步的。对于大的同步写,传输时间是决定性因素。当以大于 128KB 写时,客户端占大部份的写延迟,因为需要取得互斥锁,同时要将数据异步刷出。
图8:OSD 写性能随着 OSD 集群大小增加而线性增加,直到交换机在有 24 个 OSDs 后达到饱和。CRUSH 以及哈希性能当 PGs 的变化量小于 OSD 使用时性能会得到提升。
6.1.2 写延迟
图7显示了单个写者在不同写大小以及复本数据下的同步写的延迟。因为主OSD 同时传送更新到所有的复本上,因此小的写导致了多于两个复本下轻微的写延迟增加。对于更多的写者,传输的代价基本占据写延迟时间。1MB 的写(未显示)在单复本下需要13ms,当达到3个复本需要2.5倍的延迟时间(33ms)。当异步刷出数据并在有互斥锁的情况下,Ceph 客户端在写大于128KB的情况下要多比这个时间多一些。另外,对于写共享的应用,可以使用 O_LAZY。由于一致性的缓解,客户端可以缓存小的写,然后将大的异步提交到 OSDs 中。对应用来说,其看到的唯一的延迟就来自于客户端要填满正在将数据刷出到磁盘的缓存空间所要求的时间。
6.1.3 数据分布与扩展性
Ceph 的性能随 OSD 的扩展几乎是线性增加。CRUSH 通过一种伪随机的方式将数据进行分布,因此 OSD 的利用就能够准确地通过二项式建模或者常规方式分配。无论哪一个都可以取得完美的随机过程[29]。随着 PG 的增加,差异就下降:对于每个 OSD 100 个 PG的情况下,标准差是 10%;对于1000 个的情况下为 3%。图 8 显示了当集群扩展时,利用 CRUSH 情况下每个 OSD 的写吞吐。它将通过线性的方式在OSD中的 4096 到 32768 个 PGs 里进行数据分配。比较了测试数据,线性的分布策略极好地将负载在集群中平衡。但是简单的哈希函数无法处理设备失效以及 OSD 变动的情况。因为数据通过 CRUSH 来进行分配,如果哈希比较乱,那么在 PGs 较少的情况下,其吞吐会有所下降:因为 OSD 使用的差异变化大,那么会导致请求队列的长度会在我们客户端的散乱的负载下发生抖动(飘移)。因为设备有可能变得过满或者使用过度,从而拖累性能,CRUSH 通过卸载所有的分配碎片到一个特定的 OSD 上从而来修正这样的问题。与哈希以及线性策略不同,CRUSH 同时也最小化了数据在集群扩展产生的迁移,同时又保证了负载的平衡。CRUSH 的计算复杂度为 O(log(n))(对于有 n 个 OSD 的集群),因此只需要 10 几个微秒就可以使集群增长到好几千个 OSDs。
6.2 元数据性能
Ceph 的MDS 集群提供了增强的 POSIX 语义,并且有极佳的可扩展性。我们测试了在没有数据 IO 的情况下的部分工作负载,OSDs 在这些实验里用来单独做为元数据存储使用。
6.2.1 元数据更新延迟
我们首先考虑一下与元数据更新相关的延迟(如mknod 或者 mkdir)。一个客户端产生一系列的创建文件或者目录的动作,为了安全起见,MDS 必须将这些日志在 OSDs 之间进行同步。我们考虑两个无盘 MDS,在上面所有的元数据都存储在一个共享的 OSDs 集群上,其中一个有个本地盘用做主 OSD,并存储日志。图9(a)显示了与元数据更新的延迟(y),包括不同的元差异元数据复本(x)(0表示完全没有日志)。日志项首先被写到主 OSD 中然后被复制到其他的 OSD中。由于有本地磁盘,最开始的从 MDS 到本地主 OSD 设备所用的时间是最少的,这样使得 2 复本的更新延迟与 1 复本的无盘模式中的延迟类似。在两种情况下,多于两个复本时,由于复本并行更新会导致增加一些额外的延迟。
6.2.2 元数据读延迟
元数据的读操作(如readir,stat,open)有一些复杂。图9(b)显示了客户端在有 10000 个内嵌目录情况下,使用 readir 遍历每个目录,并 stat 每个文件时所产生的累积时间(y)。主 MDS 缓存减少了 readdir 的时间。后续的 stat 则不受影响,因为 inode 的内容已经内嵌在了目录中。因此一次对 OSD 的读就可以将整个目录的内容取到缓存(cache)中。一般来说,累积的 stat 时间会在大型目录中占大绝大部分。后续与 MDS 的交互可以通过 readdir 的额外操作来消除。在这个操作中,stat 操作与 readdir 操作会被绑定在一个单一的操作里,或者通过释放 POSIX,使得 stat 后立即跟着 readdir 来为客户端产生 Cache(这是默认行为)。 (a) 带有有盘或者无盘的元数据更新延迟,0 表示没有日志。 |
(b) 在文件系统中遍历时的累积时间。
|
图9:使用本地磁盘可以降低写延迟,因为没有开始我网络来回开销。当使用 readdirplus 或者缓和一致性使得 MDS 在执行 readdir 后调用 stat 时不需要与 MDS 进行交互,因此读能从中 Cache 中受益。
图10:每个 MDS 的吞吐在不同的负载下与集群大小下的表现。当集群增大到 128 个结点时,性能下降不会多于 50%,在大多的负载下,不会处于线性扩展线之下(水平线),这使得在现有系统上大幅提高性能。
6.2.3 元数据扩展
我们评测了元数据的扩展性,利用的是处于LLNL(Lawrence Livermore National Laboratory,劳伦斯利夫摩尔国家实验室)的 430 个结点的 alc Linux 集群的部分结点。图10显示了每个 MDS 作为 MDS 集群大小的函数的吞吐量(y),这样横轴就完美地表现出线性规模。在 mkdir 的负载中,每个客户端创建一个内嵌有 4 层的目录,并在每个目录下生成 10 个文件。MDS 的平均吞吐量在小集群中的 2000 ops/MDS,到128个MDS 结点的集群中的 1000ops/MDS(总体超过 100000 ops/S)。在 makefile 的负载中,每个客户端创建数千个文件到一个目录下,当高等等级的写被检测到时,Ceph 对共享的目录进行哈希,然后将目录的修改时间在 MDS 结点之间进行同步。打开共享的负载是通过让每个客户端重复打开关闭10个共享文件的方式来验证。在 openssh 的负载中,每个客户端重新执行文件系统跟踪,并在一个私有目录下进行编译。另一种方式则是使用共享 /lib 目录来做一般共享,而其他的共享 /usr/include,这个目录会被重度读取。打开共享以及openssh+include 负载具有最密集的读操作,因此显示了最糟糕的扩展行为,因为我们认为没有客户端复本的选择问题。openssh+lib 扩展的情况要比一般可分离 makedir 情况要好一些,因为它包括相对较少的元数据修改以及共享。尽管我们认为在消息层网络与线程的竞争在更大的 MDS 集群中会进一步降低性能,但是专门用于测试在大型集群里的专有访问模式时间有限,导致没有对其进行全面的测试与调查。图11展示了4个,16个以及64个MDS结点的集群在make dir 负载的情况下的延迟(y)与单 MDS 吞吐(x)的情况。越大的集群对于负载的分担情况越不理想,导致了更低的单 MDS 吞吐量(但是,对于整体来说是越大的)以及更高的延迟。图11:在不同集群大小(makedirs 产生的负载)平均延迟与单MDS吞吐量。
尽管线性扩展并不完美,但是一个128结点的 MDS 集群运行我们的原型时,能够每秒提供25万个元数据操作(128结点,平均2000ops/S)。由于无数操作与数据的IO是无关的,并且元数据大小与文件大小无关,视文件大小,这就相当于安装了数百 P 数据的存储。例如,在 LLNL 的“蓝色基因/L”创建了检查点的科学计算应用上,包括了 64000 个点,而每个结点有两个处理器,并且向同一个目录中不同的文件写入数据(有点像 Makefile 这样的负载)。当前的存储系统峰值达到 6000ops/S,然后需要花数分钟来完成检查点,而 128 结点的 Ceph MDS 集群在2秒中内就可以完成。如果每个文件都是 10MB(对于 HPC 的应用中是比较小的),以及 OSD 保持50MB/S,25000 个 OSD 达到饱合的情况下(如果两复本则为 50000),这样的集群写能够达到 1.25TB/S。250GB 的 OSDs 可以组合成 6 PB 的集群。更为重要的是,Ceph 的动态元数据分布使得 MDS 集群(任何大小)是按照当前的负载来分布元数据的,就算所有的客户端访问之前存于单个 MDS 之上的元数据。这样就使得其比任何的静态分区策略都更能够应对不同的应用情况。
7 经验
我们很高兴,并惊讶于在我们的设计中,文件的分配元数据以及分布函数是如此简单。虽然这对于函数本身提出了更高的要求,但是只要我们精确地实现了相应的需求,CRUSH 就能够提供相应的可扩展性,灵活性与可靠性。这不但使我们能够向客户端以及 OSDs 提供完整,独立的的数据分布的知识的同时,也极大地简化了元数据负载,后续也可以使我们能够代理数据复本的处理,包括迁移、失效检测,OSDs 的恢复,并将这些机制以有效的方式在集群中分布,同时也平衡了系统资源如 CPU以及内存的使用。RADOS 也为未来的改进打开了方便之门,将 OSD 的模型进行更智能的影射,例如位错误检测(就像 Google File System[7]中所做的)以及根据负载情况的动态复本(类似于AutoRAID[34])。尽管使用已经存在的内核文件系统做为本地对象存储(就像其他很多的文件系统所做的[4,7,9])有非常大的吸引力,但是我们很早就意识到为对象存储系统定制一个不同的文件系统,会为对象负载提供更好的性能。
我们所没有料到的是,已有的文件系统接口对于我们的需求来讲有如此大的差异,这成为我们开发 RADOS 的复本与可靠性机制的最根本的原因。EBOFS 在用户态下进行开发进展如此之快,同时提供了非常好的性能,也向我们的应用暴露了很好的接口。在 Ceph 中所得到的最大的教训就是 MDS 负载均衡的重要性要先于全局的可扩展性,以及元数据在存于哪,什么时候存的选择上的复杂性。尽管我们的设计原则与目标看起来非常简单,但是在数百个 MDS 中的负载的分布与演化却有很多精巧之处。最明显的,MDS 的性能有很多的指标,例 CPU,内存(以及Cache),包括网络,IO 限制,这些问题任何时候都可能成为性能约束。另外,有时在总体的吞吐量以及公平性上的平衡点很难去定量分析;在某种不平衡的元数据分布环境下能够提高系统的总体吞吐量[30]。客户端接口的实现,我们预期会有更大的挑战。尽管使用 FUSE 极大地简化了实现,但同时也引入了特有的问题。DIRECT_IO 绕过了内核的页绑存,但不支持 mmap,使得我们不得不修改 FUSE 来无效掉干净的页来解决这个问题。就算是最简单的应用操作,FUSE 也需要实现自己的安全检查,导致了大量的 getattrs(stat) 操作。最后,内核与用户态基于页的 IO 操作,限制了总体的 IO 性能。尽管直接与客户端连接避免了 FUSE 的问题,在系统过载时,用户空间的调用会引入一些问题(大多数我们都已经全面地检查过了),不可避免地需要我们在内核态的去实现客户端。
8 相关工作
高性能可扩展的文件系统一直以来都是HPC 社区的目标,这样的应用会使得文件系统要承担很重的负载[18,27]。尽管很多的文件系统都满足这样的需求,但是它们却无法提供与 Ceph 一样的可扩展性。像 OceanStore 以及 Farsite 这样的大规模系统,都是设计用来提供高可靠性的 PB 级别的存储,也能够同时向数千个客户端提供访问独立文件,但是受限于其子系统的(例如名字查找)的瓶颈限制,它们无法向成由千上万个协同客户端提供高性能地访问某个小文件集。相反地,并行的文件系统像 Vest[6],Galley[17],PVFS[12],以及 Swift 对于数据有扩展性支持,就是将数据在多个磁盘之间进行条带化,以此来取得非常高的传输率,但是对于可扩展元数据访问以及高可靠的数据分布缺乏良好支持。例如,Vesta 允许应用将他们的数据存在磁盘上,并允许独立地访问磁盘上的数据,而不需要访问元数据。然而,与其他很多并行文件系统一样,Vesta 并不提供元数据查找的扩展性支持。结果,这些文件系统都无一例外地在访问小文件时,或者需要许多的元数据操作时,系统性能很差。他们都有文件块分配的问题:块要么集中分配,要么通过一种锁机制进行分配,这导致他们在面对数千个客户端访问数千个磁盘的写请求的时候不能提供很好的可扩展性。
GPFS 以及 StorageTank 部分地将元数据与数据管理解藕了,但是由于有对于磁盘块的使用以及元数据分布架构的限制,这种解藕是很有限的。基于网格的文件系统,像 LegionFS[33] 设计用于广泛的使用领域,但对在高性能的本地系统中却没有进行优化。相似的,GFS(Google File System) 对于大文件以及包含大容量写与附加写这类的大负载有了优化。像Sorrento[26],其目标是用于一些非 Posix 语义的应用中。最近,很多的文件系统以及平台,包括 Federated Array of Bricks(FAB)[23]以及 pNFS[9] 都围绕网络附加存储进行设计[8]。Lustre[4],Panasas 文件系统[32], ZFS,Sorrento 以及 Kybos[35] 都是基于对象存储的方案,并与 Ceph 非常相近。然而,他们中没有一个像 Ceph 一样,将可扩展、可适配元数据管理,可靠性以及容错性集于一身。Lustre 以及 Panasas 在特定的失效下能够代理 OSDs 的责任,并对有效分布元数据管理提供了一定的支持,但却限制了它们的可扩展性和性能。另外,Sorrento 使用了一致哈希是一个例外,所有其他系统都使用显式的文件影射来指定对象的存储位置,因此对于新加入设备加入后的负载均衡提供的支持有限。这导致负载的不对称性以及很差的资源利用率,而 Sorrento 的哈希分布,缺乏像 CRUSH 对于有效的数据迁移,设备权重分配以及域失效的支持。
9 未来的工作
某些 Ceph 核心模块还没有实现,包括 MDS 失效检测以及几个 Posix 调用。两个安全架构以及协议变体正在考虑当中,但是还没有完成一个[13,19]。我们也打算调查一下的客户端在名字空中对 inode 转换元数据的回调机制的可行性。对于文件系统静态区域,这使得打开操作(用于读)不用与 MDS交互即可完成。因此,几个 MDS 的增强功能也在计划中,包括创建目标结构的任意子树的快照功能。尽管在对某个目录或者文件的访问出现拥塞时,Ceph 会动态复制元数据,但是对于数据来说却还没有这样的功能。我们计划允许 OSDs 能够根据负载动态调整单个对象的复本级别,并且在 PG 中多个 OSDs 之间分布 read 流量。这可以使得能够可扩展地访问少量的数据,并且可以在合适粒度的 OSD 间利用与 D-SPTF[15]相似的负载平衡机制。最后,我们还工作于开发一种服务质量框架,使得合并基于类型的流量优先机制和 OSD 有管理的带宽与延迟保证。另外,为了支持应用的 QoS 需求,使能够利用常规流量即可平衡 RADOS 复制与恢复操作。许多的 EBOFS 的增强功能也在计划中,包括增强的分配逻辑,数据搜索,校验以及其他的位错误检测机制的增强等,以此来保证数据安全。
10 结论
通过占用设计空间中的一个唯的点?,Ceph提出了存储系统的三个关键问题——可扩展性,性能和可靠性。通过分离设计假设,像几乎所有文件系统中都存在的分配列表,我们就可以最大化地将数据的元数据管理与数据进行分离,并且进行独立地扩展。这样的分离依赖于 CRUSH,一种产生准随机的分布函数,使得客户端能够计算对象的位置不是是查的他们的位置。为了保证数据的安全性,CRUSH 强制数据复本在不同的失效域中分布,这样又可以有效地处理大型存储系统的天生的动态性,在这样的系统中,设备失效,扩展,重构都是很平常的。RADOS 在 OSDs 之间进行智能地调整,以此来管理数据的复制,失效检测与恢复,低级磁盘分配,调度与数据迁移,而不需要一个或者多个中央的服务器。尽管对象可以当成普通的文件存储在通用的文件系统中,但是EBOFS提供了更好的语义以及更好的性能,这正是 Ceph 的负载以及接口需求所要求的。最后,Ceph的元数据管理框架解决了高可扩展性的存储集群中最烦人的问题,即如何来有效地提供单一且一致的目录层级的同时,又遵守 Posix 语义,并且随着元数据服务器的增加,性能能够随之增强。Ceph 的动态子树分区是独特的可扩展方案,不仅提供了效率,也提供了针对不同负载的可适配能力。Ceph 在 LGPL 协议下进行授权,并可在 http://ceph.sourceforge.net/ 取得。
致谢
本工作是在美国能源部,并通过加洲大学,劳伦斯.利夫摩尔国家实验室赞助下完成的,合同号为W-7405-Eng-48。研究工作部分由劳伦斯.利夫摩尔,Los Alamos,以及 Sandia 国家实验室提供基金。我们在此感谢 Bill Loewe, Tyce McLarty,Terry Heidelbeg, 与 LLNL 中的每个人,他们与我们一起讨论存储系统的方方面面以及其中的困难,他们也帮助我们利用了两天 alc 专用访问时间。我们也要感谢 IBM 捐助了32结点的集群,以此来协助大多数 OSD 性能测试,以及国家科学基金,他们支付了交换机升级的费用。Chandu Thekkath(我们的导师),包括那些隐名的评论人,还有 Theodore Wong 他们都提供了很多有价值的回馈,我们同时也感谢存储系统研究中心(Storage Systems Research Center)的学生与工作人员,他们提供了很多帮助与支持。
参考文档
[1] A. Adya, W. J. Bolosky,M. Castro, R. Chaiken, G. Cermak, J. R. Douceur, J. Howell, J. R. Lorch, M.Theimer, and R.Wattenhofer. FARSITE: Federated, available, and reliable storagefor an incompletely trusted environment.
In Proceedings of the5th Symposium on Operating Systems Design and Implementation (OSDI), Boston,MA, Dec. 2002. USENIX.
[2] P. A. Alsberg and J. D.Day. A principle for resilient sharing of distributed resources. In Proceedingsof the 2nd International Conference on Software Engineering, pages 562–570.IEEE Computer Society Press, 1976.
[3] A. Azagury, V. Dreizin,M. Factor, E. Henis, D. Naor, N.Rinetzky, O. Rodeh, J. Satran, A. Tavory, and L. Yerushalmi. Towards an objectstore. In Proceedings of the 20th IEEE / 11th NASA Goddard Conference on MassStorage Systems and Technologies, pages 165–176, Apr. 2003.
[4] P. J. Braam. The Lustrestorage architecture. http://www.lustre.org/documentation.html, Cluster File Systems,Inc., Aug. 2004.
[5] L.-F. Cabrera and D. D.E. Long. Swift: Using distributed disk striping to provide high I/O data rates.Computing Systems, 4(4):405–436, 1991.
[6] P. F. Corbett and D. G.Feitelson. The Vesta parallel file system. ACM Transactions on ComputerSystems, 14(3):225–264, 1996.
[7] S. Ghemawat, H.Gobioff, and S.-T. Leung. The Google file system. In Proceedings of the 19thACM Symposium on Operating Systems Principles (SOSP ’03), Bolton Landing, NY,Oct. 2003. ACM.
[8] G. A. Gibson, D. F.Nagle, K. Amiri, J. Butler, F. W. Chang, H. Gobioff, C. Hardin, E. Riedel, D.Rochberg, and J. Zelenka. A cost-effective, high-bandwidth storage architecture.In Proceedings of the 8th International
Conference onArchitectural Support for Programming Languages and Operating Systems (ASPLOS),pages 92– 103, San Jose, CA, Oct. 1998.
[9] D. Hildebrand and P.Honeyman. Exporting storage systems in a scalable manner with pNFS. TechnicalReport
CITI-05-1, CITI,University of Michigan, Feb. 2005.
[10] D. Karger, E. Lehman,T. Leighton,M. Levine, D. Lewin, and R. Panigrahy. Consistent hashing andrandom trees: Distributed caching protocols for relieving hot spots on theWorld Wide Web. In ACM Symposium on Theory of Computing, pages 654–663, May1997.
[11] J. Kubiatowicz, D.Bindel, Y. Chen, P. Eaton, D. Geels, R. Gummadi, S. Rhea, H. Weatherspoon, W.Weimer, C. Wells, and B. Zhao. OceanStore: An architecture for global-scalepersistent storage. In Proceedings of the 9th International Conference onArchitectural Support for Programming Languages and Operating Systems (ASPLOS),Cambridge, MA, Nov. 2000. ACM.
[12] R. Latham, N. Miller,R. Ross, and P. Carns. A nextgeneration parallel file system for Linuxclusters. Linux-
World, pages 56–59, Jan.2004.
[13] A. Leung and E. L.Miller. Scalable security for large, high performance storage systems. InProceedings of the 2006 ACMWorkshop on Storage Security and Survivability. ACM,Oct. 2006.
[14] B. Liskov, S. Ghemawat,R. Gruber, P. Johnson, L. Shrira, and M. Williams. Replication in the Harp file
system. In Proceedingsof the 13th ACM Symposium on Operating Systems Principles (SOSP ’91), pages226– 238. ACM, 1991.
[15] C. R. Lumb, G. R.Ganger, and R. Golding. D-SPTF: Decentralized request distribution inbrick-based storage
systems. In Proceedingsof the 11th International Conference on Architectural Support for ProgrammingLanguages and Operating Systems (ASPLOS), pages 37–47, Boston, MA, 2004.
[16] J. Menon, D. A. Pease,R. Rees, L. Duyanovich, and B. Hillsberg. IBM Storage Tank—a heterogeneousscalable SAN file system. IBM Systems Journal, 42(2):250– 267, 2003.
[17] N. Nieuwejaar and D.Kotz. The Galley parallel file system. In Proceedings of 10th ACM InternationalConference on Supercomputing, pages 374–381, Philadelphia, PA, 1996. ACM Press.
[18] N. Nieuwejaar, D. Kotz,A. Purakayastha, C. S. Ellis, and M. Best. File-access characteristics ofparallel scientific workloads. IEEE Transactions on Parallel and DistributedSystems, 7(10):1075–1089, Oct. 1996.
[19] C. A. Olson and E. L.Miller. Secure capabilities for a petabyte-scale object-based distributed filesystem. In
Proceedings of the 2005ACM Workshop on Storage Security and Survivability, Fairfax, VA, Nov. 2005.
[20] B. Pawlowski, C.Juszczak, P. Staubach, C. Smith, D. Lebel, and D. Hitz. NFS version 3: Designand implementation. In Proceedings of the Summer 1994 USENIX TechnicalConference, pages 137–151, 1994.
[21] O. Rodeh and A.Teperman. zFS—a scalable distributed file system using object disks. InProceedings of the 20th IEEE / 11th NASA Goddard Conference on Mass Storage Systemsand Technologies, pages 207–218, Apr. 2003.
[22] D. Roselli, J. Lorch,and T. Anderson. A comparison of file system workloads. In Proceedings of the2000
USENIX Annual TechnicalConference, pages 41–54, San Diego, CA, June 2000. USENIX Association.
[23] Y. Saito, S. Frølund,A. Veitch, A. Merchant, and S. Spence. FAB: Building distributed enterprisedisk arrays
from commoditycomponents. In Proceedings of the 11th International Conference onArchitectural Support for Programming Languages and Operating Systems (ASPLOS),pages 48–58, 2004.
[24] F. Schmuck and R.Haskin. GPFS: A shared-disk file system for large computing clusters. InProceedings of the 2002 Conference on File and Storage Technologies (FAST),pages 231–244. USENIX, Jan. 2002.
[25] M. Szeredi. File Systemin User Space. http://fuse.sourceforge.net, 2006.
[26] H. Tang, A. Gulbeden,J. Zhou, W. Strathearn, T. Yang, and L. Chu. A self-organizing storage clusterfor parallel data-intensive applications. In Proceedings of the 2004 ACM/IEEEConference on Supercomputing (SC ’04), Pittsburgh, PA, Nov. 2004.
[27] F. Wang, Q. Xin, B.Hong, S. A. Brandt, E. L. Miller, D. D. E. Long, and T. T. McLarty. File systemworkload analysis for large scale scientific computing applications. InProceedings of the 21st IEEE / 12th NASA Goddard Conference on Mass StorageSystems and Technologies, pages 139–152, College Park, MD, Apr. 2004.
[28] S. A. Weil. Scalablearchival data and metadata management in object-based file systems. TechnicalReport
SSRC-04-01, Universityof California, Santa Cruz, May 2004.
[29] S. A. Weil, S. A.Brandt, E. L. Miller, and C. Maltzahn. CRUSH: Controlled, scalable,decentralized placement of replicated data. In Proceedings of the 2006 ACM/IEEEConference on Supercomputing (SC ’06), Tampa, FL, Nov. 2006. ACM.
[30] S. A. Weil, K. T. Pollack,S. A. Brandt, and E. L. Miller. Dynamic metadata management for petabyte-scalefile systems. In Proceedings of the 2004 ACM/IEEE Conference on Supercomputing(SC ’04). ACM, Nov. 2004. [31] B. Welch. POSIX IO extensions forHPC. In Proceedings of the 4th USENIX Conference on File and Storage Technologies(FAST), Dec. 2005.
[32] B. Welch and G. Gibson.Managing scalability in object storage systems for HPC Linux clusters. InProceedings of the 21st IEEE / 12th NASA Goddard Conference on Mass Storage Systemsand Technologies, pages 433–445, Apr. 2004.
[33] B. S. White, M. Walker,M. Humphrey, and A. S. Grimshaw. LegionFS: A secure and scalable file system supportingcross-domain high-performance applications. In Proceedings of the 2001 ACM/IEEEConference on Supercomputing (SC ’01), Denver, CO, 2001.
[34] J. Wilkes, R. Golding,C. Staelin, and T. Sullivan. The HP AutoRAID hierarchical storage system. InProceedings of the 15th ACM Symposium on Operating Systems Principles (SOSP’95), pages 96–108, Copper Mountain, CO, 1995. ACM Press.
[35] T. M. Wong, R. A.Golding, J. S. Glider, E. Borowsky, R. A. Becker-Szendy, C. Fleiner, D. R.Kenchammana- Hosekote, and O. A. Zaki. Kybos: self-management for distributedbrick-base storage. Research Report RJ 10356, IBM Almaden Research Center, Aug.2005.
[36] J. C. Wu and S. A.Brandt. The design and implementation of AQuA: an adaptive quality of serviceaware
object-based storagedevice. In Proceedings of the 23rd IEEE / 14th NASA Goddard Conference on MassStorage
Systems andTechnologies, pages 209–218, College Park, MD, May 2006.
[37] Q. Xin, E. L. Miller,and T. J. E. Schwarz. Evaluation of distributed recovery in large-scale storagesystems. In Proceedings of the 13th IEEE International Symposium on High PerformanceDistributed Computing (HPDC),
pages 172–181, Honolulu,HI, June 2004.