一种日志结构文件系统的设计与实现(三)

一种日志结构文件系 统的设计与实现(三)

The Design and Implementation of a Log-Structured file system


Mendel Rosenblum and John K. Ousterhout

Electrical Engineering and Computer Sciences, Computer Science Division

University of California

Berkeley , CA 94720

mendel@sprite.berkeley.edu, ouster@sprite.berkeley.edu

 

邓辉

<!-- -->

3.2 、空闲空间管理:段

       日志结构文件系统中最困难的设计问题是空闲空间的管理。其目标是要提供新数据写入所需要的大的空闲块。一开始,所有的空闲空间是作为一整块存在于磁盘上的,但是随着日志占满磁盘,空闲空间就会被分割成许多小的块,对应于那些被删除或者被覆写的文件。

 

       此时,文件系统有两种选择:线索化( threading )和拷贝。图 2 对此进行了说明。第一种方法是保持活动数据不动,使日志穿过空闲块。糟糕的是,线索化会导致空闲空间分片更加严重,大块的连续写入变得不再可能,日志结构文件系统也就不再比传统的文件系统更快。第二种方法是在日志中拷贝活动数据,以空余出大的空闲块用于写操作。在本文中,我们假设活动数据以一种紧致的方式被协会到日志的头部;也可以被移到另外一个日志结构文件系统从而形成一个日志层次结构,或者被移动到某个完全不同的文件系统或存档中。拷贝方法的缺点就是其成本,尤其是对那些长期活动的文件;针对日志以圆形环绕磁盘工作这种最简单的情形,在日志环绕磁盘的每一遍中,所有长期活动的文件都必须被拷贝一次。

 

       Sprite LFS 使用了一种线索化和拷贝相结合的方法。磁盘被分成大的固定大小的块,称为 。所有的段都是从头到尾顺序写入的,在覆写一个段之前,该段中的所有活动数据都必须拷贝出来。不过,日志也按照逐段的方式被线索化起来;如果系统能够把那些长期活动的数据放到到一些段中,那么这些段可以被略过,这样就可以避免重复的数据拷贝。段的大小也被定的足够大,使得读或者写一个整块所需的传输时间远远大于寻找到该块开始处所需要的时间。这样,无论对块的访问顺序如何,针对整块的操作速度都可以接近磁盘带宽的速度。 Sprite LFS 当前使用的块大小为 512K 或者 1M

3.3 、段清理机制

       把活动数据从段中拷贝出来的过程被称为段的清理 。在 Sprite LFS 中,它是一个

简单的由 3 个步骤组成的过程:把一定数量的段读入到内存中,识别活动数据,并把活动数据写回到数量少一些的干净段中。这个操作完成后,那些被读取的段会被标识为干净,可以被新数据使用或者进行额外的清理。

 

       作为段清理的一部分,必须能够识别出段中哪些块是活动的,这样它们就可以被再次写出。同时,也必须能够识别出每个块所属的文件以及块在文件中的位置;这个信息是更新文件的 inode 使其指向该块的新位置所需要的。 Sprite LFS 解决上面两个问题的方法是:针对每个段,它都把一个段摘要块( segment summary block 作为其一部分写入。这个摘要块标识出了写入该段中每条信息;例如,对于每个文件数据块,摘要块中都含有该块的文件编号和块编号。当需要多个日志写入操作才能填满一个段时,该段中可以包含多个段摘要块。(当文件缓存中缓冲的脏块的数目不足以填满一个段时,就会出现段的部分写入情况)。在写入时,段摘要块所导致的开销很小,并且其在崩溃恢复(参见第 4 节)和清理过程中都非常有用。

 

       Sprite LFS 还用段摘要信息来区分活动块和需要被覆写或者删除的块。一旦知道了一个块的标识,就可以通过检查文件的 inode 或者间接块来判断是否仍然有指向该块的合适的块指针,从而判断其活性。如果有,那么该块就是活动的;如果没有,那么该块就非活动。 Sprite LFS 对这项检查进行了些许优化,其在每个文件的 inode 映射项中保存了一个版本编号;每当文件被删除或者长度被归零时,这个版本号就会递增。版本号和 inode 号一起形成了文件内容的唯一标识符( uid )。段摘要块中针对段中的每个块都记录了这个 uid ;如果在进行段清理时,发现某个块的 uid inode 映射中保存的当前 uid 不匹配,该块就会被立即丢弃,无需检查文件的 inode

 

       这种清理方法意味着 Sprite 中没有空闲块列表或者位图之类的东西。这样做除了节省内存和磁盘空间之外,同时也简化了崩溃恢复。如果存在这些数据结构,那么记录该结构的更改日志以及在崩溃后的一致性恢复工作,都需要有额外的代码来完成。

3.4 、段清理策略

       上面我们介绍了段清理的基本机制,在清理策略方面,有四个必须要解决的问题:

1、  段清理器应该何时运行?一些可能的选择为:以一直以低优先级在后台运行,或者在晚上运行,或者仅在磁盘空间快耗尽时运行。

2、  每次要清理多少个段?段清理提供了一个对磁盘数据进行重新组织的机会;每次清理的段的数目越多,重组的机会就越大。

3、  要清理哪些段?那些分片最严重的段是明显的选择,但是结果表明这不是最好的选择。

4、  在重写活动数据时,该如何对其进行组织呢?一种可能的方法是尽量保证后续读操作的本地化,例如可以把同一目录下的文件聚集在一个段中。另一种可能的方法是基于最后修改时间对块进行排序,把老旧程度相似的块聚集到新的段中;我们称这种方法为年龄排序( age sort

 

       到目前为止,我们还没能系统地解决上述策略问题中的前两个。 Sprite LFS 在干净段的数码低于某个门限值时(一般是几十个),就开始段的清理工作。每次清理几十个段,直到干净段的数目超过另外一个门限值(一般为 50-100 )。 Sprite LFS 的总性能对于门限值的准确选择似乎不是非常敏感。相反,第 3 4 个策略决策至关重要:以我们的经验来看,它们是决定日志结构文件系统性能的主要因素。第 3 节的剩余部分会探讨我们对于段的选择和活动数据聚集策略的分析。

 

       我们用术语写入成本( write cost 来对不同的清理策略进行比较。写入成本是指,新数据中的每个字节写入磁盘所花费的平均时间,其中包括所有清理开销。写入成本被表示成在没有清理开销并且以全部带宽速度(没有寻道时间、没有旋转延迟)写入数据的情况下所花费时间的倍数。写入成本为 1.0 是理想情况:数据以全部磁盘带宽速度写入,并且没有清理开销。写入成本为 10 意味着,磁盘最大带宽中仅仅 1/10 被实际用于新数据的写入;其他都花费在寻道、旋转以及清理上面。

 

       如果日志结构文件系统中把段设置得大一些,那么和写入以及清理相比,寻道和旋转延迟可以忽略不计,这样写入成本就等于移入和移出磁盘的总字节数除以新数据的字节数。这个成本由要清理的段的使用率(仍然活动的数据比率)所决定。在稳定状态,每当要把数据写入一个段时,清理器都必须得产生一个新的干净段。为了完成这项工作,它得读入 N 个完整的段,并把活动数据写入 N*u 个段中(其中 u 为段的利用率, 0≤u<1 )。这个过程产生

N*(1-u) 个段大小的连续空闲空间用于新数据的写入。因此

 

write = total bytes read and written / new data written

= (read segs + write live + write new)/new data written

= (N + N*u + N*(1-u))/(N*(1-u))

=2/(1-u)                                                                  (1)

 

在上述公式中,我们做了个保守的假设:为了获取段中的活动块,必须要把读取整个段;在实际中,仅仅读取活动块会更快一些,尤其是当利用率很低时(我们没有在 Sprite LFS 尝试这种做法)。如果一个要清理的段中没有任何活动块( u=0 ),那么就不要读取任何字节,因此写入成本为 1.0

 

       在图 3 中,我们把写入成本表示成 u 的函数。作为参考,图中给出了 Unix FF S 针对小文件的情况,可以看出其最多使用了磁盘带宽的 5-10% ,相应的写入成本为 10-20 (更详细的度量,请参见 [11] 5.1 节中的图 8 )。通过日志、延迟写入以及对磁盘请求排序等方法,这个值可能会被提升到 25% (写入成本为 4 )。从图 3 中可以看出,要想使日志结构文件系统的性能超过当前的 Unix FFS ,被清理段的利用率必须得小于 0.8 ;要想超过改善版的 Unix FFS ,利用率必须得小于 0.5

 

       值得注意的是,上面讨论的利用率并不是指整个磁盘中包含活动数据的比例;而是指要被清理的段中包含活动数据的比例。文件使用上的变化会导致段之间利用率上的不同,清理器可以选择去清理那些利用率最低的段;它们的利用率要小于整个磁盘的平均利用率。

 

       即使这样,也可以通过降低整个磁盘的利用率来提升日志结构文件系统的性能。磁盘的利用率越低,被清理段所包含的活动块就越少,从而写入成本就越低。日志结构文件系统提供了一种成本 - 性能权衡:如果磁盘的利用率较低,那么就可以获得高的性能,但是每个可用字节的成本就会很高;如果增加了磁盘的利用率,那么存储成本和性能都会得到降低。这种在性能和空间利用率之间的权衡并不是日志结构文件系统所独有的。例如, Unix FFS 仅允许文件占用 90% 的磁盘空间。其余 10% 被保留下来,用于空间分配算法的高效运转。

 

       在日志结构文件系统中,以低成本获取高性能的关键在于:让磁盘进入一种双峰的段分布模型,其中大多数段是接近满的,少部分是空的或者接近空的,清理器几乎总是可以去清理那些空段。这样,总体上高的磁盘利用率就也能够提供低的写入成本。在下面的小节中,会介绍我们是如何在 Sprite LFS 中得到这样一种双峰分布的。

3.5 模拟结果

(待续)

 

阅读更多
想对作者说点什么?

博主推荐

换一批

没有更多推荐了,返回首页