原论文:Ceph: A Scalable, High-Performance Distributed File System (OSDI’06)
Ceph简介及关键技术要点
Ceph是一个高性能、可扩展的分布式文件系统,旨在提供出色的性能、可靠性和可扩展性。为了最大化数据和元数据管理的分离,它使用了一种称为CRUSH(Controlled Replication Under Scalable Hashing)的伪随机数据分布函数(为异构且动态的不可靠对象存储设备(OSDs)集群设计的)。Ceph利用设备智能,将数据复制、故障检测和恢复分布到半自治的OSDs上,这些OSDs运行一个专门的本地对象文件系统。Ceph还具有一个动态分布式元数据集群,提供极其高效的元数据管理,并无缝适应各种通用和科学计算文件系统工作负载。Ceph在各种工作负载下的性能测试表明,它具有出色的I/O性能和可扩展的元数据管理,支持每秒超过250,000个元数据操作。
Ceph的一些关键技术要点:
-
分离数据和元数据管理:Ceph通过消除文件分配表,使用生成函数来解耦数据和元数据操作,从而允许Ceph利用OSDs中的智能来分布数据访问、更新序列化、复制和可靠性、故障检测和恢复的复杂性。
-
CRUSH数据分布:Ceph使用CRUSH来分配对象到存储设备上,这种方法允许任何一方计算(而不是查找)组成文件内容的对象的名称和位置,消除了维护和分发对象列表的需要。
-
动态分布式元数据管理:Ceph的元数据集群架构基于动态子树划分,适应性地和智能地在数十甚至数百个MDSs之间分配管理文件系统目录层次结构的责任。
-
可靠的自治分布式对象存储:Ceph将数据迁移、复制、故障检测和恢复的责任委托给存储数据的OSDs集群,同时在高层次上,OSDs集体向客户端和元数据服务器提供单一的逻辑对象存储。
-
客户端操作:Ceph客户端在每个主机上运行,向应用程序提供文件系统接口。客户端维护自己的文件数据缓存,独立于内核页面或缓冲区缓存。
-
元数据存储:Ceph的MDS集群通过同步应用元数据更新来确保序列化、一致性、正确的安全性和安全性。
-
复制:Ceph使用一种变体的主要副本复制来管理其自己的数据复制,同时采取措施最小化对性能的影响。
-
故障检测和恢复:Ceph通过让每个OSD监控与其共享放置组(PGs)的对等OSDs来分布式地执行故障检测。
-
性能和可扩展性评估:Ceph在一系列微基准测试中被评估,以证明其性能、可靠性和可扩展性。
-
未来工作:Ceph的一些核心元素尚未实现,包括MDS故障恢复和几个POSIX调用。Ceph还计划探索客户端回调在名称到inode转换元数据上的实用性,以及开发服务质量(QoS)架构,以支持基于类的流量优先级和OSD管理的带宽和延迟保证。
Ceph通过其独特的设计和功能,解决了大规模存储系统中的可扩展性、性能和可靠性这三个关键挑战,为需要处理大量数据的应用程序提供了一个强大和灵活的存储解决方案。
原论文阅读
1. Introduction
- 性能提升的追求:系统设计者一直在寻求提高文件系统性能的方法,这对于广泛的应用程序类别的整体性能至关重要。科学和高性能计算社区特别推动了分布式存储系统性能和可扩展性的进步。
- 传统解决方案的局限性:传统的解决方案,如NFS,提供了一个简单的模型,服务器导出文件系统层次结构,客户端可以将其映射到本地名称空间。尽管广泛使用,客户端/服务器模型的集中化已成为可扩展性能的显著障碍。
- 基于对象的存储:更近期的分布式文件系统采用了基于对象存储的架构,其中传统的硬盘被智能对象存储设备(OSDs)所取代。OSDs将传统的块级接口替换为允许客户端对更大的(通常是可变大小的)命名对象进行读写的接口,将低级块分配决策分散到设备本身。
- 元数据工作的分布:尽管采用了基于对象的存储模型,但由于元数据工作负载的分布不足,这些系统继续受到可扩展性限制。对传统文件系统原理的持续依赖,如分配列表和inode表,以及不愿将智能委托给OSDs,进一步限制了可扩展性和性能,并增加了可靠性的成本。
- Ceph的设计目标:Ceph的设计目标是在提供卓越的性能和可靠性的同时,承诺更高的可扩展性。Ceph的架构基于这样一个假设:在PB级别的系统中,系统是动态的:大型系统的数据是在不断增长的,节点故障是常态而非例外,工作负载的质量和特性随着时间的推移不断变化。
- 数据和元数据操作的解耦:Ceph通过消除文件分配表并用生成函数替代它们,来解耦数据和元数据操作。这使得Ceph能够利用OSDs中存在的智能来分布围绕数据访问、更新序列化、复制和可靠性、故障检测和恢复的复杂性。
- 适应性强的分布式元数据集群:Ceph利用一个高度适应性强的分布式元数据集群架构,极大地提高了元数据访问的可扩展性,从而提高了整个系统的可扩展性。
2. System Overview
- Ceph文件系统的三个主要组件:
- 客户端:每个客户端实例向主机或进程提供接近POSIX的文件系统接口。客户端可以直接链接到客户端实例,或通过FUSE(用户空间文件系统接口)挂载文件系统。
- OSD集群:OSDs共同存储所有数据和元数据。客户端直接与OSDs进行文件I/O(读和写)操作。
- 元数据服务器集群:管理文件系统命名空间(文件名和目录),同时协调安全性、一致性和数据的完整性。
- Ceph接口的接近POSIX:Ceph接口被认为是接近POSIX的,因为它适当地扩展了接口,并有选择地放宽了一致性语义,以更好地与应用程序的需求对齐,并提高系统性能。
- 架构的主要目标:可扩展性(达到数百PB甚至更多)、性能和可靠性。可扩展性考虑了多个方面,包括系统的总体存储容量和吞吐量,以及单个客户端、目录或文件的性能。
- 目标工作负载:Ceph的目标工作负载可能包括极端情况,如成千上万的主机同时从一个文件中读取或写入,或在同一个目录中创建文件。这些场景在超级计算集群上运行的科学应用程序中很常见,也预示着未来通用工作负载的趋势。
- Ceph的三个基本设计特点:
- 解耦数据和元数据:Ceph最大化了文件元数据管理与文件数据存储的分离。Ceph消除了传统的文件分配表,取而代之的是一个名为CRUSH的专用数据分布函数。CRUSH函数预测性地将文件数据分片到可命名的对象上,同时分配对象到存储设备上。这样,任何一方都可以计算(而不是查找)文件内容组成的对象的名称和位置,从而无需维护和分发对象列表。并且客户端可以直接与OSDs通信/交互来执行文件I/O操作,从而提高了整体可扩展性。
- 动态分布式元数据管理:Ceph使用一种基于动态子树划分的新颖元数据集群架构,适应性地和智能地在多个MDSs之间分配管理文件系统目录层次结构的责任。
- 可靠的自治分布式对象存储:Ceph将数据迁移、复制、故障检测和恢复的责任委托给存储数据的OSDs集群。
3. Client Operation
3.1 File I/O and Capabilities
- 文件I/O处理:当进程打开文件时,客户端会向元数据服务器(MDS)集群发送请求。MDS遍历文件系统层次结构,将文件名解析为文件的inode,包含唯一的inode号、文件所有者、模式、大小和其他每个文件的元数据。如果文件存在且访问被允许,MDS将返回inode号、文件大小和用于将文件数据映射到对象的条带化策略的信息。
- 能力(Capabilities):如果客户端还没有能力,MDS会发放能力给客户端,指定允许执行的操作。能力目前包括控制客户端读取、缓存读取、写入和缓冲写入的四个比特位。将来,能力将包括安全密钥,允许客户端向OSDs证明它们被授权读取或写入数据(当前prototype信任所有客户端)。
- 条带化策略:Ceph泛化了一系列条带化策略,将文件数据映射到一系列对象上。为了避免需要文件分配元数据,对象名称简单地结合了文件inode号和条带号。然后,使用CRUSH将对象副本分配给OSDs。
- 文件读取和写入:如果客户端打开文件进行读取,MDS授予它们读取和缓存文件内容的能力。配备inode号、布局和文件大小信息的客户端可以直接从OSD集群中定位并读取包含文件数据的所有对象。类似地,如果客户端打开文件进行写入,它将被授予带有缓冲的写入能力,并且客户端在文件的任何偏移量处生成的任何数据都直接写入适当的对象上。写入完成后,客户端向MDS提供新的文件大小(写入文件的最大offset)。
3.2 Client Synchronization
- 同步I/O:POSIX语义合理要求读取反映先前写入的任何数据,并且写入是原子的(即,重叠的并发写入的结果将反映特定的发生顺序)。当多个客户端打开文件进行读写或混合读写操作时,MDS会撤销之前发放的读缓存和写缓冲能力,强制客户端对该文件的I/O操作进行同步。这意味着每个应用程序的读或写操作都会阻塞,直到OSD确认,从而将更新序列化和同步的负担放在存储每个对象的OSD上。
- 对象锁定:当写操作跨越对象边界时,客户端会获取受影响对象的独占锁(由相应的OSD授予),并立即提交写入和解锁操作以实现所需的序列化。对象锁也被用来通过异步获取锁和刷新数据来掩盖大写操作的延迟。
- 性能影响:同步I/O可能对应用程序的性能产生显著影响,尤其是对于那些进行小读或小写的应用程序,因为至少需要一轮到OSD的往返行程时间。尽管在通用工作负载中读写共享相对较少见,但在高性能计算(HPC)应用程序中更为常见,其中性能通常是关键。
- 一致性与性能的权衡:Ceph支持通过全局开关来放宽一致性,以提高性能,许多其他分布式文件系统也在这方面做出了妥协。然而,这种解决方案既不精确也不满意:要么性能受损,要么一致性在整个系统中丢失。
- POSIX接口的扩展:为了解决这个问题,高性能计算社区提出了一套POSIX I/O接口的高性能计算扩展,其中一部分由Ceph实现。最显著的是,它们包括一个用于打开的
O_LAZY
标志,允许应用程序明确放宽共享写入文件的通常一致性要求。 - 应用程序控制一致性:performance-conscious的应用程序可以管理它们自己的一致性(例如,通过写入同一文件的不同部分,这是HPC工作负载中的常见模式),然后允许在本应同步执行I/O时缓冲写入或缓存读取。如果需要,应用程序可以通过两个额外的调用显式同步:
lazyio_propagate
将给定的字节范围刷新到对象存储,而lazyio_synchronize
确保先前传播的效果在任何后续读取中得到反映。
3.3 Namespace Operations
- 命名空间操作管理:客户端与文件系统命名空间的交互由元数据服务器集群管理。这包括读操作(例如,readdir、stat)和更新操作(例如,unlink、chmod)。
- 同步应用:为了确保序列化、一致性、正确的安全性和安全性,所有元数据操作都是由MDS同步应用的。为了简单起见,不向客户端发出元数据锁或租约。
- 优化常见访问模式:Ceph优化了最常见的元数据访问场景。例如,
readdir
后跟每个文件的stat
(例如,ls -l
)是一个非常常见的访问模式,也是大型目录中臭名昭著的性能杀手。在Ceph中,readdir
只需要一个MDS请求,该请求获取整个目录,包括inode内容。 - 缓存和一致性:默认情况下,如果
readdir
紧接着一个或多个stats
,那么缓存的信息将被返回;否则,它将被丢弃。虽然这在一定程度上放宽了一致性,因为可能会忽略掉介入的inode修改,但为了极大地提高性能,我们愿意做出这种权衡。 - 扩展命名空间操作:Ceph通过
readdirplus
扩展明确捕获了这种行为,它与目录条目一起返回lstat
结果。Ceph可以选择通过更长时间地缓存元数据来进一步放宽一致性,如NFS通常缓存30秒。然而,这种方法破坏了一致性,例如使用stat
来确定文件是否已更新的应用程序——它们要么返回结果不正确,要么需要等待旧缓存值超时。 - 正确的行为和接口扩展:Ceph选择提供正确的行为,并在影响性能的情况下扩展接口。这在选择由多个客户端打开用于写入的文件的
stat
操作时表现得最为明显。为了返回正确的文件大小和修改时间,MDS撤销任何写入能力,暂时停止更新,并从所有写入者那里收集最新的大小和mtime值。最高的值与stat回复一起返回,并且重新发放能力以允许进一步的进展。
4. Dynamically Distributed Metadata
4.1 Metadata Storage
- 内存缓存与磁盘持久化:尽管MDS集群的目标是从内存缓存中满足大多数请求,但为了安全起见,元数据更新必须提交到磁盘。Ceph使用一组大型、有界的、延迟刷新的日志,允许每个MDS快速地将其更新的元数据流式传输到OSD集群中。
- 日志的作用:每个MDS的日志可以吸收重复的元数据更新(这在大多数工作负载中都很常见),这样在旧的日志条目最终被刷新到长期存储时,许多条目已经过时。
- MDS恢复:虽然原型中尚未实现MDS恢复,但日志被设计成在MDS故障的情况下,另一个节点可以快速扫描日志来恢复失败节点内存缓存的关键内容(以便快速启动),并在这样做的过程中恢复文件系统状态。
- 存储策略:Ceph采用了两级存储策略,旨在最小化与元数据相关的磁盘I/O,并通过动态子树划分(Dynamic Subtree Partitioning)来最大化局部性和缓存效率。
- 元数据结构:文件和目录元数据在Ceph中非常小,几乎完全由目录条目(文件名)和inode(80字节)组成。与常规文件系统不同,Ceph不需要文件分配元数据——对象名称是使用inode号构建的,并通过CRUSH分布到OSDs。
- 高效的目录局部性:每个目录的内容都使用与元数据日志和文件数据相同的条带化和分布策略写入OSD集群。Ceph通过单个OSD读取请求预取整个目录,利用大多数工作负载中存在的高目录局部性。
- inode编号:inode编号在元数据服务器中分配范围,并在文件删除时被认为不可变。将来,它们可以轻松地重新分配。
- 锚点表:一个辅助锚点表通过inode编号全局寻址罕见的多个硬链接inode,而不会拖累单链接文件的常见情况,使其带有庞大、稀疏且笨重的inode表。
4.2 Dynamic Subtree Partitioning
- 元数据操作的重要性:元数据操作通常占文件系统工作负载的一半,并且位于关键路径上,这使得MDS集群对于整体性能至关重要。元数据管理也是分布式文件系统中的一个关键扩展挑战。
- 动态子树划分策略:Ceph的MDS集群基于动态子树划分策略,这种策略适应性地将缓存的元数据分层分布在一组节点上。每个MDS通过使用具有指数时间衰减的计数器来测量目录层次结构中元数据的流行度。
- 负载分布:MDS负载值定期比较,适当大小的目录层次结构子树被迁移以保持工作负载均匀分布。共享长期存储和精心构建的命名空间锁使得这种迁移可以通过将适当内容的内存缓存传输到新的权威节点来进行,对一致性锁或客户端能力的影响最小。
- 元数据分区:Ceph将文件系统目录映射到元数据服务器上,根据当前工作负载动态地进行。当目录变得“热门”时,它们的内容会被选择性地复制到多个节点以分散负载。特别大或承受重写工作负载(例如,许多文件创建)的目录将按文件名在集群中进行哈希处理,以实现平衡分布。
- 元数据复制:当元数据在多个MDS节点之间复制时,inode内容被分成三组,每组具有不同的一致性语义:安全(所有者、模式)、文件(大小、修改时间)和不可变(inode号、创建时间、布局)。
- 锁管理和访问模式:不可变字段从不改变,而安全和文件锁由独立的有限状态机管理,每个状态机都有不同的状态和转换,旨在适应不同的访问和更新模式,同时最小化锁争用。
4.3 Traffic Control
- 热点和流量高峰:分区目录层次结构可以在广泛的工作负载下平衡负载,但可能无法应对热点问题或流量高峰,即许多客户端访问同一个目录或文件的情况。
- 元数据流行度知识:Ceph利用对元数据流行度的了解,仅在需要时为热点提供广泛的分布,避免在一般情况下产生相关开销和损失目录局部性。
- 选择性复制:大量读取的目录内容(例如许多打开操作)有选择地在多个节点上复制,以分散负载。对于特别大或承受大量写入工作负载(例如许多文件创建)的目录,其内容通过文件名在集群中进行哈希,实现平衡分布,以牺牲目录局部性为代价。
- 适应性方法:这种适应性方法允许Ceph在特定情况下捕获粗粒度和细粒度分区的好处,确保在最有效的部分和文件系统的特定情况下使用这些策略。
- 客户端学习元数据分区:每个MDS响应都向客户端提供有关权威和任何副本的相关inode及其祖先的更新信息,允许客户端学习与它们交互的文件系统部分的元数据分区。
- 客户端操作定向:未来的元数据操作将根据给定路径的最深已知前缀,针对权威(用于更新)或随机副本(用于读取)进行定向。通常,客户端学习不受欢迎(未复制)的元数据位置,并能够直接联系适当的MDS。访问受欢迎元数据的客户端被告知元数据位于不同的或多个MDS节点上,有效地限制了认为任何特定元数据位于任何特定MDS上的客户端数量,分散潜在的热点和流量高峰。
5. Distributed Object Storage
Ceph客户端和元数据服务器将对象存储集群看作是单个逻辑对象存储和命名空间。Ceph’s Reliable Autonomic Distributed Object Store (RADOS)可以通过分布式地委托对象及其副本的管理、集群扩展、故障检测、OSDs的恢复来实现容量和汇集性能上的线性扩展。
5.1 Data Distribution with CRUSH
- 数据分布的重要性:Ceph需要在不断变化的成千上万个存储设备集群中分配PB级别的数据,以便有效利用设备的存储和带宽资源。
- 随机化数据分布策略:为了避免数据不平衡或负载不对称,Ceph采用随机化策略来分配新数据,迁移现有数据的随机子集到新设备,并从移除的设备中重新分配数据。
- CRUSH算法:Ceph首先使用简单的哈希函数将对象映射到放置组(PGs),通过可调整的位掩码来控制PGs的数量。然后,使用CRUSH算法将PGs分配到OSDs上,该算法能够高效地将每个PG映射到存储对象副本的有序OSD列表。
- CRUSH的优势:CRUSH算法的两个关键优势是:它是完全分布式的,任何一方(客户端、OSD或MDS)都可以独立计算任何对象的位置;而且,OSD集群图谱更新不频繁,几乎消除了与分布相关的元数据交换。
- 数据定位问题:CRUSH同时解决了数据分布问题(“我应该在哪里存储数据”)和数据定位问题(“我存储数据在哪里”)。
- 存储集群图谱:CRUSH需要存储集群图谱,这是一个描述组成存储集群的设备的紧凑、分层描述。小的变化对存储集群的影响很小,最小化了由于设备故障或集群扩展导致的数据迁移。
- 放置规则和权重:CRUSH根据放置规则映射PGs到OSDs,这些规则定义了复制级别和放置的任何约束。每个OSD还有一个权重值,用于控制分配给它的数据量。
- 集群图谱的层次结构:集群图谱的层次结构与物理或逻辑组成和潜在故障源相一致。例如,一个四层层次结构可能适用于由OSDs组成的货架、装满货架的机柜和机柜行的安装。
5.2 Replication
- 数据复制的重要性:Ceph假设在PB或EB级别的系统中,故障是常态,因此需要管理自己的数据复制,以可扩展的方式维护系统可用性和数据安全。
- 基于主副本的复制:Ceph使用一种变体的主要副本复制模型,其中数据被复制到称为放置组(PGs)的多个OSDs上。客户端将所有写入操作发送到一个对象的PG中的第一个非故障OSD(主副本),该OSD分配一个新的版本号给对象和PG,并将写入操作转发到任何额外的副本OSDs。
- 写入操作的处理:在每个副本OSD应用更新并向主副本响应后,主副本在本地应用更新并向客户端确认写入操作。读取操作则直接指向主副本。
- 客户端的简化:这种复制方法简化了客户端处理副本同步或序列化的复杂性,将这些任务转移到OSD集群的内部网络上,集群内部的带宽更加充足。
- 副本OSD的故障处理:如果副本OSD出现故障,主副本会忽略这些故障,因为在后续的恢复过程中(见第5.5节),系统将可靠地恢复副本的一致性。
- 数据安全:Ceph区分同步和安全性,允许实现低延迟的更新以进行高效的应用程序同步,同时提供明确定义的数据安全语义。
5.3 Data Safety
- 数据写入的可见性:在分布式存储系统中,客户端对数据更新的可见性感兴趣,希望更新能够尽快对其他客户端可见,尤其是当多个写入者或混合读写操作迫使客户端进行同步操作时。
- 数据持久性的确认:客户端还希望确认他们写入的数据已经安全地复制到磁盘上,并且在电源故障或其他故障情况下能够存活。
- 同步与安全性的分离:RADOS(Reliable Autonomic Distributed Object Store)将同步操作与数据的安全性分离,允许Ceph实现低延迟的更新和明确的数据安全语义。
- 写入操作的确认流程:主副本在所有OSDs的内存缓冲缓存中应用更新后,向客户端发送确认(ack)。这允许同步的POSIX调用在客户端返回,而最终的提交通知则在数据安全地提交到磁盘后才发送给客户端。
- 写入缓冲:默认情况下,客户端还会缓冲写入操作,直到它们提交,以避免在电源故障时丢失数据。在恢复期间,RADOS允许重新执行之前确认的(因此有序的)更新,在接受新更新之前的固定时间间隔内。
- 失败恢复:在设备故障恢复期间,OSDs会检索缺失或过时的对象,并独立地负责从其对等节点检索缺失或过时的对象。如果OSD接收到对陈旧或缺失对象的请求,它将延迟处理,并将该对象移到恢复队列的前面。
5.4 Failure Detection
- 及时故障检测的重要性:及时的故障检测对于维护数据安全至关重要,但随着集群规模扩大到成千上万个设备,故障检测变得更加困难。
- OSD故障报告:对于某些故障,如磁盘错误或数据损坏,OSDs可以自我报告。而对于使OSD在网络中无法访问的故障,则需要主动监控,Ceph通过让每个OSD监控与之共享放置组(PGs)的对等OSDs来分布式地执行这一任务。
- 利用现有复制流量:在大多数情况下,现有的复制流量作为被动的生命确认,无需额外的通信开销。如果一个OSD最近没有收到对等OSD的消息,它会发送一个明确的ping。
- OSD的生存性维度:RADOS考虑了OSD生存性的两个维度:OSD是否可达,以及CRUSH是否为其分配了数据。对于无响应的OSD,最初会被标记为down,其所有主要责任(更新序列化、复制)暂时移交给其放置组中的下一个OSD。
- 故障恢复和集群更新:如果OSD未能快速恢复,它会被标记为out,并从数据分布中移除,每个PG会加入另一个OSD以重新复制其内容。等待处理的客户端简单地重新提交到新的primary。
- 故障报告的收集和过滤:一个小型的监控器集群收集故障报告,并在中央过滤掉瞬态或系统性问题(如网络分区)。监控器使用选举、主动对等监控、短期租约和两阶段提交来集体提供对集群图的一致和可用访问。
- 避免系统性问题的数据处理:RADOS避免由于系统性问题而启动广泛的数据复制,通过标记OSD为down但不out(例如,在所有OSDs的电源故障后)来实现。
5.5 Recovery and Cluster Updates
- OSD集群图的变更:由于OSD故障、恢复或显式集群变更(如新增存储设备的部署),Ceph的OSD集群图会发生变化。
- 快速恢复:为了加快恢复速度,OSDs维护每个对象的版本号和每个放置组(PG)的最近更改日志(包括更新或删除的对象的名称和版本)。
- PG责任的确定:当一个活跃的OSD接收到更新后的集群图,它会遍历所有本地存储的放置组,并计算CRUSH映射以确定它负责哪些PG,无论是作为主副本还是副本。
- PG状态的同步:如果PG的成员资格发生变化,或者OSD刚刚启动,OSD必须与PG的其他OSDs对等。对于复制的PG,OSD提供当前的PG版本号给主副本。如果OSD是PG的主副本,它会收集当前(和以前的)副本的PG版本。
- 数据恢复和同步:如果主副本缺少最新的PG状态,它会从当前或以前的OSDs中检索PG更改日志(或完整的内容摘要,如果需要的话),以确定正确的(最新的)PG内容。然后,主副本向每个副本发送增量日志更新(或完整的内容摘要,如果需要的话),这样所有参与方都知道PG内容应该是什么,即使它们本地存储的对象集可能不匹配。
- 并行恢复:由于故障恢复完全由各个OSDs驱动,因此受影响的每个PG将与(很可能不同的)替换OSDs并行恢复。这种基于Fast Recovery Mechanism (FaRM)的方法减少了恢复时间,并提高了整体数据安全性。
5.6 Object Storage with EBOFS
- EBOFS的设计:EBOFS是为了满足对象存储工作负载的特定需求而设计的,它在用户空间完全实现,并直接与原始块设备交互,从而允许定义自己的低级对象存储接口和更新语义。
- 用户空间的优势:用户空间的实现提供了更大的灵活性和更容易的实现,同时避免了与Linux VFS(虚拟文件系统)和页面缓存的复杂交互,这些是为不同的接口和工作负载设计的。
- EBOFS的核心特性:EBOFS支持原子事务(例如,多个对象的写入和属性更新),并且更新函数在内存缓存更新时返回,同时提供异步提交通知。
- 磁盘调度和写入策略:EBOFS积极安排磁盘写入,并选择在后续更新使它们过时时取消挂起的I/O操作。这为其低级磁盘调度器提供了更长的I/O队列,相应地提高了调度效率。
- B树服务:EBOFS设计的核心是一个强大、灵活且完全集成的B树服务,用于在磁盘上定位对象、管理块分配和索引集合(放置组)。
- 块分配和碎片管理:块分配是以范围(起始位置和长度对)的形式进行的,而不是块列表,以保持元数据紧凑。磁盘上的空闲块范围按大小分组并按位置排序,使EBOFS能够快速找到靠近写入位置或磁盘上相关数据的空闲空间,同时限制长期碎片化。
- 内存中的元数据:除每个对象的块分配信息外,所有元数据都保存在内存中,以提高性能和简化设计(即使是对于大量数据,元数据也相当小)。
- 写入时复制(Copy-on-Write):EBOFS积极执行写入时复制:除了超级块更新外,数据总是写入磁盘的未分配区域。