Ceph:一个可缩放的高性能的分布式文件系统

概要


我们已经开发了Ceph,一个分布式的文件系统,它提供杰出的性能,可靠想和可缩放性。Ceph通过伪随机数据分布替换分配表(CRUSH)为不可靠对象存储设备(OSD)的异构动态集群设计,以最大限度分离了数据和元数据管理。我们通过分布式数据副本,失败探测以及恢复到专用本地对象文件系统的半自助操作系统来利用设备的智能。动态分布式元数据集群提供了非常有效的元数据管理并且无缝的适配到一般用途范围和特定的科学计算文件系统负载。各种工作负载下的性能测量展示了,ceph有着杰出的I/O性能和可扩展的元数据管理,支持超过每秒250000元数据操作

1 介绍

系统设计长期以来为增强文件系统的性能,应用的广泛的类型的应用程序的整体性能十分重要。科学和高性能的计算团体在现实中驱动了性能和分布式存储系统的前进,通常提前纪念预测更通用的需求。传统的解决方案在NFS中列举的,在它暴露的文件系统中提供了简单的模型,客户端可以映射它到本地命名空间。虽然被广泛使用,客户端和服务端模型内在的集中化以及被展示是缩放性能明显的障碍。

i-node 是一种数据结构,主要用于类 Unix 文件系统(如 Ext 文件系统、UFS 等)。每个文件或目录在文件系统中都有一个唯一的 i-node。i-node 中包含了与文件相关的元数据和信息。其中包括文件类型,权限信息,拥有者 ,时间戳,文件大小,数据块指针。

分配列表:是一种记录文件在磁盘上数据块分配情况的数据结构。它用于跟踪哪些数据块被占用,哪些数据块是空闲的。分配列表的特点包括:

最近的分布式文件系统已经采用了基于对象存储的体系结构,传统的硬件磁盘被替换为智能的对象存储设备(OSD)它结合了CPU网络接口,和本地缓存与底层磁盘或者RAID。OSD替换了传统的块级接口,其中客户端可以读取或写入字节,范围到更大(通常大小不一)的命名对象,分布式低级块,将低级块的决策发送给设备本身。客户端通常与元数据服务(MDS)交互以执行元数据操作(打开,重命名),同时直接与OSD交流,明显的提高了整个扩展性。

扩展性限制可能是因为元数据的集中管理(而不是分布在不同节点上的)。

这里的“不愿意将智能委托给OSD”意思是大部分决策和处理任务交给客户端或者元数据服务。而不委托给OSD

采用了这个模型的系统遭受到可扩展性的限制,由于元数据负载很少或者没有分布继续依赖传统的文件系统原则,类似分配列表和inode表以及不愿意将智能委托给OSD,进一步限制了可伸缩性能,并增加了可靠性成本。

我们提出了Ceph一个分布式文件系统它提供优秀的性能和可靠性的同时承诺无与伦比的所放性。我们的架构是基于这样的假设系统在PB尺度上是动态的:大尺度的系统不可避免的以递增的方式构建,节点的故障是常态而非意外,质量和负载的特性总是随着时间改变。

Ceph通过消除文件分配表件给他们替换为一般的函数,解耦了数据和元数据操作。这允许Ceph接管OSD中现有的智能以分布围绕数据访问,更新序列化复制和可靠性,异常探测与恢复。Ceph利用了高度自适应的分布式元数据集群架构,它动态增强元数据访问的扩展性,从而提高了整个系统可伸缩性。

我们讨论目标并且,工作量假设激励我们在架构设计中做出选择,分析它在系统尺度和性能尺度的影响,并且结合我们在实现功能系统原型方面的经验。

2 系统总览


图1:系统架构。客户端通过直接连接到OSD执行文件I/O。每个机场南可以直接同时连接到客户端实例或者和挂载的文件系统交互。

Feph文件系统有三个主要的组件:客户端,每个实例都暴露类似paxos的文件系统接口到主机或者进程;OSD的cluster,它共同存储了所有的数据和元数据;以及元数据服务集群,它管理命名空间(文件和目录)的同事协调安全性一致性和连续性(见图1)。我们说Ceph接口是类似paxos的因为我们发现扩展接口和选择型的发送一致性语义以更好的和应用的需求保持一致以增加系统的性能是合适的。

架构的主要目标是可缩放性(到数百PB甚至更多),性能,额和可靠性。在多个维度提供可扩展性包括整个存储容量,系统吞吐量和单个客户端,目录,或者文件的性能。我们的目标负载可能包括了这样的极端例子比如,上万甚至上百万的主机同时读取或者写入到相同的文件或者在目录下创建相同的文件。这样的情节在特定应用或者超级计算集群中很常见,越来越多的预示着为了的通用工作负载。更重要的是,我们认识到分布式文件系统的工作负载本质上是动态的,随着活动应用程序和数据集的变换,数据和元数据访问会发生重大变换。Ceph直接解决了可伸缩性的问题同时实现了高性能,可靠性和可用性,通过一下的三个基础设计特征:解耦数据和元数据,动态分布数据管理,可靠的自动分布对象存储。

因为GFS只允许追加所以读取是可以和修改并行的(你只要指定读取偏移量就可以了)

解耦数据和元数据 Ceph最大限度地将文件元数据管理与文件数据存储分离开来。元数据操作(打开,重命名等)通过元数据服务集群进行共同管理,其中客户端直接和OSD进行交互以执行文件I/O(读取和写入)。对象存储长期以来承诺通过将低级块分配决策委托给各个设备,从而改善文件系统的可扩展性。但是,与现有的基于文件系统的对象相比,它们用较短的对象列表取代了较长的文件块列表,Ceph完整的消除了文件列表。作为替代,文件数据被分割到可预测的命名对象,同时一个特殊用途的数据分布函数叫做Crush指派对象到存储设备中。这允许任何一方进行计算而不只是查找抱函文件内容的对象路径和名,消除了维护和犯法对象的需要,简化了系统设计,减少了元数据集群的负担

动态分布的元数据管理 因为文件系统元数据操作的占典型文件系统工作的一半之多。有效的元数据管理是整个系统性能的关键。Ceph利用了新颖的基于动态子树分区元数据架构,它能够适应并智能分发职责以管理文件系目录层级在数十甚至数百的MDS中。一个(动态)分级分区在每个MDS中保存分区,促进有效更新和主动获取以增加通用负载的性能。值得注意的是,元数据服务之间的工作负载分配是基于是完全基于当前访问的模式的,ceph允许任何工作负载下有效的利用可用的MDS资源,并且实现MDS数量的线性扩展。

可靠的自主分配对象存储 由成千上万个设备组成的大型系统本质上是动态的:它们是增量构建的,它随着新的存储被部署以及佬的设备推移而增加与收缩,设备的失败是频繁且可预料的大型的数据卷被创建移动和删除。所有的这些元素都要求数据的分布能够有效利用可用的资源和维护数据复制的所需级别。Ceph委托数据迁移,失败探测和故障恢复到存储数据的OSD集群,而在更高的层级上,OSD同时提供单一逻辑对象存储到客户端和元数据服务。这个方法允许Ceph更有效的使用每个OSD上的能力(CPI和内存)来实现可靠性,高可用对象存储和线性缩放。

我们描述了Ceph客户端的操作,元数据服务集群,和分布式对象存储,以及它们通过我们架构的关键特性发挥影响。

3 客户端操作

我们通过ceph的客户端操作,介绍了整个Ceph的组件操作和应用。Ceph客户端运行在每个主机执行的应用代码并且暴露文件系统接口道应用。在Ceph协议中,客户端代码完全的运行在用户空间,可以链接到它或者通过FUSE(user-space文件系统接口)作为文件系统来访问。每个客户端维护自身的文件数据缓存,独立于核心页或者缓冲区缓存,使得直接链接到该客户端的应用程序可以访问这些数据。

3.1 文件I/O和能力

“Striping”(条带化)是一种数据存储技术,通常用于提升存储系统的读写性能。它将文件或数据分块(称为“条带”),并将这些条带分布存储在多个存储设备或节点上。这样,读取或写入操作可以并行进行,从而提高了整体数据吞吐量。

当进程打开文件客户端发送请求到元数据服务,元数据服务贯穿文件系统层级以转换文件名到文件inode她包括了特定的inode号,文件持有者,模型,大小,和其他每个文件的元数据。如果文件已经存在并且有访问权限,元数据服务返回inode数量,文件大小和将文件映射到对象的条带化存储技术 。元数据服务还可以向客户机发出一个能力(如果它还没有),指定允许进行哪些操作。当前的能力包括四个bit,控制客户端的读取,缓存读取,写入,缓冲写入权限。在未来,能力将会包括秘钥,允许客户端向OSD证明,它们被授权写入数据(当前协议信任所有的客户端)。后续的元数据服务在文件I/O中的的参与仅限于管理保持文件一致性和适当的语义能力。

Ceph泛化了一系列条带化策略,将文件数据映射到对象序列上。以避免需要文件分配元数据,对象名称可以简单的将文件inode号和条带号组合起来。然后使用CRUSH将对象副本分配给OSD,CRUSH是一个全局一直的映射函数(见5.1节)。例如,如果一个或多个客户端打开文件然后进行读访问,MDS赋予他们读取和缓存文件内容的能力。有了inode号布局和文件大小,客户端可以命名和定位包含文件数据的所有对象并且直接从OSD集群上进行读取。任何不存在的对象或者字节范围都被定义为文件漏洞或者零。类似的如果客户端打开文件进行写入,它被授予使用写缓冲的能力,文件中的任何偏移量产生的任何数据都会被简单的写入适当的对象。客户端在文件关闭的时候放弃能力,并且向MDS提供新的文件大小(最大的写入偏移量),它重新定义了(可能)已经存在并且包含数据的一组对象。

3.2 客户端同步

严格一致性(Strict Consistency):严格一致性要求所有的读写操作必须立即反映在所有客户端上。例如,如果一个客户端对某个文件进行了写操作,其他客户端立即读取该文件时,必须看到这个写入的更新。严格一致性通常保证了数据的一致性和正确性,但在高并发环境下会增加延迟,因为每次写入都需要等待所有的读操作完成同步。

放松一致性(Relaxed Consistency):放松一致性允许在某些情况下,多个客户端对同一数据进行并发读写时,不必严格同步。例如,应用程序可能在不同的文件区域写入数据,并且允许每个客户端根据自己的需求缓存数据,减少同步的需求。这种方式提高了性能,但可能会导致某些客户端读取到过期的数据(因为并不是所有更新都会立即传播)。放松一致性通常适用于对性能要求高的场景,尤其是在不依赖于实时一致性的应用程序中。

POSIS语义显式要求读取读取能够反映任何之前写的数据,同时写是原子操作(即,重叠的结果并发的写入将会反映特定的发生顺序)。当文件被多个客户端打开,无论是多个写入者还是读写混合的情况,MDS将会撤回任何之前发出的读缓存和写缓冲能力,增加文件I/O为了文件同步。即,每个应用读取或写入操作将会阻塞直到被OSD确认为止。有效的将更新序列化和同步的负担交给了OSD。当写入跨越边界时,客户端尝试在受影响的对象上加锁(由各自的OSD许可),并且立即提交写入和解锁操作,已实现所需的序列化。对象所同样用于掩盖大规模写入的延迟,通过常识所并且异步刷新数据来实现。

不奇怪,同步IO可能是应用程序的性能杀手,特别是做小的读取和写入,因为延迟的代价至少需要一次往返OSD。虽然读写共享在通用工作负载中相对较少,它在科学计算应用中更加常见,其中性能通常是关键。出于这个原因,在不依赖于严格标准的一致性情况下,放松一致性通常是可取的。虽然Ceph通过全局开关支持这种发送,并且一些其他的分布式文件系统都在这个问题上进行了尝试,这是一个不精确也不让人满意的方案:要么性能遭受影响要么在系统范围内失去一致性。

也正是因为这个原因,一组高性能的计算拓展到Posix I/O接口已经被提出,通过高性能计算(HPC)交流,其中一个子集由Ceph实现。显著的,它包含了用于打开的O_LAZY标志位,该标志位允许程序明确的放宽对于共享写文件的常规一致性需求。尊重性能的应用会自行管理其一致性(即通过写入相同文件的不同部分,这是在HPC工作负载中常见的模式)然后允许缓冲写入或者缓存读取,否则将同步执行I/O。如果需要,应用可以显式的同步俩个额外的调用:lazyio_propagate将会刷新给定字节区域到对象存储,lazyio_synchronize将会确保先前转播的有效性会反应在任何之后的读取中。通过在俩个客户端之间使用同步I/O提供合适的读写和共享写语义,和并拓展应用程序接口从而保持简单性,从而为注重性能的分布式应用放松一致性。

3.3 命名空间操作

客户端和文件系统的命名空间通过元数据服务集群进行管理。读操作(读取目录统计)和更新操作(unlink, chmod)是同步的应用到MDS以确保序列化、一致性、并发安全。为了简单期间,没有元数据锁或者租约被发送到客户端。为了现实中的高性能计算工作负载,回调提供的好处很小,但是潜在的复杂性很高。

stat 是一个在操作系统中用于获取文件或文件系统状态的系统调用或命令。它提供了有关文件的详细信息,包括文件的元数据。

在 Ceph 中,inode(索引节点)是指存储在对象存储系统中的一个数据结构,用来存储文件系统中文件或目录的元数据。

而Ceph优化了大部分的元数据访问场景。一个 readdir,后面跟每个文件的stat(即 ls -l)是极为通用的访问模式并且在大量的目录下是臭名昭著的性能杀手。一个readdir在Ceph中只需要一个简单的MDS请求,它请求整个文件包括inode内容。默认情况下,如果readdir立即后跟一个或多个stats,则返回短暂缓存的信息;否则将会被丢弃。虽然这稍微放松了连续性,因为中间的inode节点修改可能会被忽视,因为性能提升明显,我们非常乐意做这个交易。这个行为通过readdirplus进行补货,它返回lstat的结果和目录项(如一些啊特定的操作系统实现getdir已经做到了)。

Ceph可以通过缓存长时间元数据来实现进一步的放松一致性,早起版本的NFS通常缓存时间为30S。然而,这种方法在某种长度上破坏了一致性,这对应用程序来说通常是至关重要的,比如那些使用stat来确定的,如果文件已经被更新了-它们的行为要么不正确要么最终等待旧的缓存超时。

当文件被多个客户端同时写入时,stat 操作需要获取最新的文件大小和修改时间。为了保证返回正确的值,MDS会撤销写入能力,暂时停止更新,收集所有写入者的最新值,这样保证了序列化一致性。虽然停止多个写者的操作看起来比较极端,但这是保证一致性的必要措施。如果只有一个写者,可以直接从客户端获取正确的值而不需要停止进程。

相反,我们再次选择正确的行为,并且扩展了实例中的对性能不利影响的接口。对由多个客户端打开的文件执行stat操作,最清楚的说明了这种选择。为了返回正确的文件大小和修改的时间,MDS撤销了所有写入的能力以随时停止更新并且收集来自写入的最新的大小和最后修改的时间值。最高的值和stat 应答一起返回 ,并且能力被重新发布以允许进一步的扩展。虽然组织多个作者死活有些极端,但为了保证合适的串行能力是必须的。(对于单个写入者,可以在不中断进程的情况下从写入客户端检索正确的值)。对于一致行为不必要的应用-paxos无法满足其需求的受害者-可以使用statlite,它通过位掩码来说明,那些位掩码字段不需要保持一致性。

4 动态分布元数据

元数据操作通常相当于文件系统工作负载的一半,并且位于关键路径上,使得MDS集群对整个系统的性能至关重要。元数据管理也在分布式文件系统中提出了关键的扩展性挑战:尽管容量和总I/O率可以缩放到几乎任意的额外的更多存储设备上,元数据操作设计更大程度的相互依赖,这使得可扩展的一致性和连续性管理更加困难。

Dynamic Subtree Partitioning(动态子树分区)是Ceph中一种用于优化元数据存储和访问的技术,旨在提高目录和元数据操作的效率,特别是在处理大规模数据集时。

具体来说,这种方法通过将元数据存储在多个不同的存储层次(如多个MDS节点)中来提升性能。其核心思想是将目录结构(尤其是大目录)划分为多个子树,并根据实际负载动态调整这些子树的分配和存储方式,以最大化缓存和数据的局部性。这种方式能够优化元数据的访问路径,使得相关的目录项和文件信息能够更快地被缓存和访问,从而减少磁盘I/O和提高整体性能。

文件和目录元数据在Ceph中非常小,几乎完全由目录条目(文件名)和索引节点(80字节)组成。不像传统的文件系统,不需要文件分配元数据-对象名称是使用inode编号构建的,使用CRUSH分布到OSD中。这简化了元数据的工作负载并且允许我们的MDS有效的管理非常大的文件工作集合,而无关与文件大小。我们的设计进一步通过使用两层存储策略来最小化与元数据相关的磁盘I/O,并且使用动态子树分区来最大化局部性和缓存有效性(Dynamic Subtree Partitioning)。

4.1 元数据存储

虽然元数据集群目的是在内存中满足大部分的请求,但是元数据的更新必须提交到磁盘以确保安全。一组大的,有界的,懒加载的日志允许每个MDS以高效的分布式的方式,快速的将其更新的元数据流传输到OSD集群中。每个MDS日志,没数百兆的字节,也吸收重复的元数据更新(大多数的工作负载都有)这样,当就的日志记录被刷新到长期存储时,许多条目已经过时了。虽然我们的原型还没有实现MDS恢复,在MDS故障的时候日志是是这样设计的,另一个节点可以快速重新扫描日志以恢复失败节点的关键内容到内存中缓存(为了快速启动),这样做可以恢复文件系统状态。

这个策略提供了俩全齐美的效果:以有效的(顺序)的方式更新流式更新流式传输到磁盘,并且大大减少了重写的工作量,允许长期的在磁盘上的存储布局变得更优以面对未来的读取访问。事实上,inode节点是直接嵌入到目录中的,允许MDS执行整个目录和单个OSD的读取请求,并且利用大多数负载存在的高度目录局部性。每个目录内容使用相同的条带化和分布策略被写入到OSD集群中就像元数据日志和文件数据一一样。inode编号在范围内分配给元数据服务,并且在原型中认为是不可变的,虽然在未来可能在文件删除之后被简单的回收。辅助的anchor table(锚表)使得具有多个硬链接的稀有inode可以通过inode号全局寻址-而不会妨碍极其常见的单链接文件的巨大、稀疏和繁琐的索引节点表。

4.2 动态子树分区

在文件系统中,静态子树分区(Static Subtree Partitioning)是一种文件系统的管理方法,用于在一个大型文件系统中为不同的用户或应用程序创建独立的子树区域,以实现资源的隔离和管理。

我们的primary拷贝缓存策略让有权的MDS负责对缓存管理和序列化更新任何给定的元数据片的更新。大多数显存的文件系统采用了基于静态子树的分区以删除以委派这种授权(通常迫使管理员将数据分为更小的静态卷),一些最近的和实验性的文件系统已经使用了hash函数以分布目录和文件元数据,为了负载分布而牺牲了本地性。这俩个方法都有严重的局限性:静态子树分区不能处理动态的负载和数据集,hash破坏了元数据的本地性和有效的元数据和存储的关键机会。


图2:ceph基于当前工作负载动态的映射文件层级子树到元数据服务。当他们遭遇热点时,单独的目录被hash穿过多个节点。

Ceph的MDS集群基于动态子树分区策略,它自适应的分布缓存元数据分层的穿过节点集合如图2所示。每个MDS在目录层级中使用带计数器的指数时间衰减衡量元数据的欢迎程度,任何操作都会增加受影响inode上的计数器,它的所有祖先节点直到根目录,为每个元数据服务器提供一个加权树用于描述最近的负载分布情况。定期比较MDS的负载值,并迁移目录层次结构中适当大小的子树,以保持工作负载均匀分布。通过将缓存中适当的内容传输到新的授权者,共享的长期存储组合并且小心的构建命名空间锁允许这样的迁移进行开展,对于一致性锁和客户端的影响最小。为了安全输入的元数据被写入到新的MD5日志,同时添加日志条目到俩端以确保权限转移故障时不会受到影响(类似俩阶段提交)。生成的基于子树的分区保持大粒度以最小化前缀复制并保持局部性。

当元数据被复制穿过多个MDS节点,inode内容被分成三组,每个具有不同一致性语义:安全(owner,mode),file(size,mtime),不可变(inode号,ctime,layout)。不可变的文件从不修改,但安全性和文件锁由独立的有限状态机控制,每个都有不同的状态组和转换设计以在所争抢的情况下提供不同的访问和更新模式。例如,在遍历路径的过程中,所有者和模式是安全检查所必须的,而锁文件反映了广阔的客户端访问模式的,因为它控制MDS发出给客户端的能力。

4.3 流量控制

分区目录的层级到多个节点可以均衡工作负载的广阔范围,但是并不能对付热点或者闪电人群,其中许多客户端访问相同的目录或者文件。Ceph利用元数据受欢迎程度的了解以提供广阔的负载只是为了热点的,在需要的时候,一般情况下不会导致相关的开销和丢失目录的位置。大量的读取目录的内容(即许多打开)是有选择的复制到多个节点以分布负载。很大的目录或者经历大量写负载占用的目录(许多文件被创建)在集群中按文件名将内容进行哈希分布,以目录的局部性为代价达到均衡的分布。这种自适应的方法允许Ceph包含广阔的分区粒度,在特定情况下,捕捉到了粗粒度的和良好的分区的好处,和文件系统中最有效的一部分。

每个 MDS 的响应都会向客户端提供有关相关 inode 及其上级节点的权限和任何副本的最新信息,允许客户端习得与其他文件系统部分的元数据分区。将来的元数据操作将基于已知路径中最深前缀,针对权限节点(用于更新)或随机副本执行。通常客户端会知道不受欢迎的(未复制的)元数据并且直接联系合适的MDS。然而,客户端访问受欢迎的元数据被告知元数据驻留在不同或多个MDS节点上,有效的限制了认为特定元数据位于特定MDS上的客户端的数量。在潜在的热点和闪电人群之前将其驱散。

5 分布式对象存储

从更高的角度来看,ceph客户端和元数据服务将对象存储集群视为单个逻辑对象存储和名称空间。ceph的可靠自主分布对象存储(Autonomic Distributed Object Store (RADOS))通过授权对象复制,集群扩张,失败检测和OSD恢复,使用分布式的方式让容量和总体性能达到了线性尺度的缩放。

5.1 使用CRUSH进行数据分布

Ceph必须分布PB的数据在上千个相关的存储设备中,因此,设备存储和带宽资源是有效被利用。以避免不稳定的(即最近部署的设备偷懒或者空闲 )后果者负载不对称(即只有新设备上的新数据和热门数据),我们采用将新的数据随机分布的策略,迁移随机的已存在数据的子样本到新的数据中,并且从已经删除的设备中一致的重新分配数据。这个随机方法在任何潜在的工作负载中都能表现的很好。


图3:文件被条带化穿过多个对象组到放置组(PG),并通过CRUSH(一个专用的副本放置功能)分布到OSD。

Ceph首先使用简单的hash函数映射对象到放置组(PG),使用可调节的位掩码以控制PG的数量。我们选择值,它给每个OSD大约100PG以平衡每个OSD的录用率的差异和复制相关元数据的数量。防治组然后使用CRUSH(可扩展哈希下的受控复制controlled replication under scalable hashing)指派到OSD。这与传统方法不同(包括其他基于对象的文件系统)其中,数据放置不依赖任何的块或者对象列表元数据。定位任何的对象,CRUSH只需要放置组和OSD集群映射:对于组成存储集群的设备进行简洁的分层的描述。这个方法有俩个关键优势:首先,它是完全分布式的任何一方(客户端,OSD,或者MDS)可以独立的计算任何对象的位置。第二,映射很少被修改,实际上消除了任何与分布相关的元数据交换。在做这个的过程中,CRUSH同时解决了数据分布问题(我应该在哪存储数据)和数据局部性问题(我应该把数据存储在哪里)。通过存储集群的设计小的修改,对现有的放置组的影响很小,减少因设备故障或集群扩容导致的数据迁移。

集群的映射封层是结构化的以对齐物理集群或者逻辑组成以及潜在的失败资源。例如,一个安装可能会形成一个四层的结构,其中包括装满OSD的架子,装满架子的机架柜和一行的机柜。每个OSD也有权重值以控制相关数据指派的数量。CRUSH基于放置规则映射PG到OSD。它定义了复制的级别和防止的限制。例如可以在三个OSD上复制每个PG,所有都落在相同的行(为了限制行间复制的流量)但是划分到了不同的机柜中(以最小化电源电路或者边缘交换关机的故障)。集群的映射还包括停机或者非活动的设备列表以及epoch号,epoch号在每次映射更改时递增。所有OSD请求都被标记为客户端map的标签,这样各方就可以就可以就当前的数据分布达成一致。增量的更新在写作的OSD之间共享,如果映射已经过期,并且如果客户端的地图已过期,就在 OSD 的回复中附带更新。

5.2 复制

与类似Lustre系统相反,它假设使用类似RAID的机制或者在SAN上进容错可以构建出一个足够健壮的OSD。我们假设PB甚至EB级别的故障是常态而不是意外,并且任何时间都有几个硬盘无法操作。易扩展的方式维护系统可用性并确保数据的安全,RADOS使用主拷贝复制的一种变体管理它的数据副本,同时采取措施劲量少对性能进行影响。

数据按照放置组进行复制,每个数据都被映射到N个ODS的有序列表(用于N向复制)。客户端发送所有的写操作到对象PG第一个为失败的OSD(primary),它指派新的版本号给对象和放置组并且转发写入到任何其他OSD副本 。在每个副本应用了修改和响应到primary,primary在本地应用修改并且写入确认到客户端。读取直接在primary上。这种方法省去了围绕副本之间的同步或序列化的复杂性,在有其他机器写入或故障恢复的情况下,它会变得很繁重。它也通过将数据从客户端复制到OSD集群的内部网络中转移了带宽消耗,我们期望更多的资源是可用的。忽略中间副本OSD的故障,任何随后的回复(见 5.5章)将会可靠的恢复副本的一致性。

5.3 数据安全

在分布式系统中,数据写入共享存储主要有俩个原因。客户端希望自己的更新对其他客户端是可见的。这应该很快:写入应该越快越好,特别是当多个写入者或者混合了读取和写入强制客户端进行同步操作。其次客户端想知道他们所写的数据是否被安全复制我,到磁盘上,并且能够在断电或者其他的故障中存活下来。RADOS在确认更新时,将同步与安全分离,允许Ceph实现低延迟更新,以实现高效的应用程序同步和定义良好的数据安全语义。

图4:当写入操作被要用到所有复制该对象的OSD上的缓冲区缓存后,RADOS会返回一个应答(ack)。只有在已经安全的提交到磁盘最终提交通知会被发送给客户端。

图4描述了信息在对象写入期间的发送。primary转发更新到副本,并且在应用了所有OSD之后更新到副本。在应用到所有OSD内存缓冲chache之后回复一个ack,允许客户端的同步posix调用返回。当数据安全的提交到磁盘中,最终的commit被发送(可能许多客户端要慢一些)。在完全复制更新后,我们才会返回发送给客户端,以无缝容忍任何单一OSD的故障。尽管这会增加客户端的延迟。默认情况下,客户机还会缓冲写操作,直到它们提交,以避免在放置组中的所有osd同时断电的情况下丢失数据。当在这种情况下回复,RADOS允许在接受更新之前以固定的顺序间隔之前确认的(因此是有序的)重放先前确认的更新。

5.4 故障探测

即使故障探测是维护数据安全的关键,但是随着集群的尺度拓展到上千台服务器开始变得困难。为了确定故障,例如磁盘错误或者陈旧的数据,OSD可以上报自身的错误,这使得OSD在网络中不可达,然而,需要主动监视,RADOS通过让每个ODS检测这些共享PG的对等体来主动分配监视。在大部分例子中,已经存在的副本流量服务。大多数情况下现有的副本流量作为存活的被动确认,没有额外的通信开销。如果一个OSD最近没有收到其他OSD的信息发送显式的ping。

RADOS考虑OSD存活的俩个维度:OSD是否可达,以及是否被CRUSH分配数据。无响应的OSD最初被标记为下线,并且任何的主要职责(更新,序列化,复制)都暂时的传递给每个放置组中的下一个OSD。如果OSD不能快速回复,它会被标记为离开数据分布,并且一个OSD加入每个PG以重新复制它的内容。对失败OSD进行花旗的客户端重新提交到新的primary。

因为网络异常现象的多样化可能导致OSD连通性间歇性的失效,一个小的Monitors集群在中心收集故障并且过滤掉短暂的系统的问题(比如网络分区)。monitors(仅部分实现)使用选举,主动的对等监视,短任期的租约和俩阶段提交共同提供了对集群映射的一致性和可用性访问。当映射被更新反应到任何故障或者故障时,受影响的OSD将提供增量的映射更新,然后通过承载现有的OSD间通信在整个集群中传播。分布式探测允许快速的探测而对monitor造成过重的负担,同时解决集中与仲裁的不一致性的发生。通过标记OSD下线但是没有离开,最重要的是RADOS避免了广泛的由于系统问题导致的数据重新复制。

5.5 恢复和集群更新

OSD集群映射由于OSD的故障,恢复,以及明确的修改部署新的集群,将会被修改。Ceph处理这些改动使用同一种方式。为了便于快速的回复,OSD维护了对于每个PG(类似Harp中的复制日志)每个对象的版本号和最近修改的日志(名字和更新或删除对象的版本)。

当活动的ODS接收到了更新集群映射,它迭代所有本地存储的放置组并且计算CRUSH映射到确定的负责人上,作为primary或者副本。如果PG成员改变了,或者OSD刚启动,OSD必须与其他的OSD对等。对于复制的PG们,OSD提供了primary和当前的版本号,如果OSD是PG的primary,它收集当前(和以前)副本的PG版本号。如果parimary服务器缺少最近的PG状态,它将从PG中当前或以前的OSD中检索最近PG更改的日志(或完整的内容摘要,如果需要的话),以便确定正确的(最近的)PG内容。然后primary发送每个副本一个递增的日志更新(如需要,可以是完全内容的摘要),以便各方都知道PG的内容应该是什么,即使他们本地存储的对象可能不匹配。只有在primary确定合适的PG状态并共享他们到全部的副本,才允许对PG中的对象进行IO操作。然后OSD独立的负责以从对等节点找回丢失或者过时的对象。如果OSD接受一个来自陈旧的,或者遗失对象的状态请求,延迟处理并且移动对象到恢复队列的前面。

例如,假设osd1崩溃,并且被标记为下线,osd2作为pgA的primary进行接管。如果osd1恢复了它会在引导时请求最后一个映射并且监视器把它标记为up。当osd2接收到结果映射更新时,它将会知道这是pgA的一个长期的primary,并且发送pgA的版本号到osd1。osd1将会从osd2中找回最近pgA的日志条目,告诉osd2它的内容是最新的,然后开始处理请求同时在后台恢复所有的更新的对象。

因为故障恢复是完全通过单独的OSD驱动的,每个遭受故障的PG将会并行的回复到(类似)不同的的替代OSD。这个方法基于快速回复机制(FaRM),减少恢复时间并提高整体数据安全性。

5.6 基于EBOFS的对象存储

虽然多样的分布式文件存储系统使用类似ext3的本地文件存储系统以管理低级别的存储,我们发现这些接口和性能不太适合对象负载。现有的内核接口限制了我们理解对象更新合适安全的提交到磁盘上的能力。同步写入或者日志提供了所需的安全性,但是伴随着更大的延迟和性能损失。更重要的,posix接口不支持原子数据和元数据(即属性)更新事务,这对于保持RADOS一致性很重要。

作为替代,每个Ceph OSD是用EBOFS管理它的本地对象存储,基于范围和B树的对象文件系统(Extent and B-tree based Object File System)。完全在用户态实现EBOFS并且直接和原始的块设备交互允许我们去定义我们自己的低级别的对象存储接口以及更新语义,它将更新序列化(用于同步)与磁盘上的提交(用于安全)分开。EBOFS支持原子事务(即写入并且分发更新到多个对象),并且更新函数在内存缓存更新时返回,同时提供异步的提交通知。

一个用户空间方法除了提供了强大灵活与更容易的实现,也避免了与Linux文件系统与页缓存的繁琐的交互,它们都是为不同的接口和工作负载设计的。虽然大多数内核文件系统会在一段时间后懒惰地将更新刷新到磁盘,但 EBOFS 会主动安排磁盘写入操作,并选择在后续更新使得之前的 I/O 操作变得多余时取消这些待处理的 I/O 操作。这为我们的低级的磁盘调度器提供了更长的I/O队列,并相应提高了调度效率。用户空间调度器还可以更容易地确定最终工作负载的优先级(客户端I/O与恢复)或者提供优质的服务保证。

中心到EBOFS的设计是健壮的,柔性并且并且完全合并了b树服务,它用于定位磁盘上的对象,管理块的分配,索引收集(放置组)。磁盘上的空闲区块按大小分类并按位置进行排序,允许EBOFS快速定位磁盘上写位置或相关数据附近的空闲空间,同时也限制了长期的碎片。除了每个对象块分配信息意外,为了高性能和简化所有的元数据都保存在内存中(即便对很大的卷它也很小)。最后EBOFS积极的执行写时复制:除了超级块的更新之外,数据总是被写入到未分配的区域。

10 结论

Ceph解决了三个关键的存储系统挑战-可缩放性,性能,和可靠性-通过在设计空间中占据一个独特的点。通过拜托在几乎所有现有系统中发现的分配列表等假设,我们最大化了元数据和数据管理的分离,允许它们独立缩放。这种分离依赖CRUSH,一个生成伪随机分布的数据分布函数,允许客户端计算对象位置,而不是查找它们。CRUSH强制故障分离数据副本,以增强数据安全的同时有效的应对大型存储集群固有的动态特性,其中设备的失败,扩容集群整改是很正常的。

RADOS利用了只能的OSD以管理数据复制,失败探测和回复,低级别的磁盘分配,调度和数据迁移不需要妨碍任何中心服务。虽然对象可以被视为文件存储在通用文件系统中,EBOFS通过寻址特定的工作负载和目前Ceph中的接口要求,提供了更多合适的语义和更号的性能。

最后,Ceph的元数据管理架构解决了在大尺度存储上一个最棘手的问题-如何有效提供遵循poxis语义的单一同意层级目录结构,其性能随着元数据服务器的数据量而扩展。Ceph的动态子树分区是一个独特的缩放方式,提供了有效和可靠性以适配多样的工作负载。

Ceph是LGPL授权的http://ceph.sourceforge.net/

Last modification:November 14, 2024
如果觉得我的文章对你有用,请随意赞赏