日志和 ReiserFS
Daniel Robbins (drobbins@gentoo.org)
总裁/CEO,Gentoo Technologies, Inc
2001 年 6 月
伴随着 Linux 2.4 版本的发行,出现了大量的文件系统可能性,其中包括 ReiserFS、XFS、GFS 和其它文件系统。这些文件系统听起来的确都很酷,但是它们真正能做些什么呢,擅长在哪些方面,以及在 Linux 产品环境下如何才能安全地使用它们呢?在高级文件系统实现者指南中,Daniel Robbins 通过向您展示如何在 Linux 2.4 的环境下建立这些新的高级文件系统来回答以上的问题。遵从这个方法,他提供了在实际实现过程中的有价值的建议,性能信息和重要的技术性注意要点,以便于您在新的文件系统中能有令人愉快的经历。在这里,也就是这个系列的第一篇文章中,他解说了日志和 ReiserFS 的优点。
准备好的内容
这一系列文章的目的是向您详实地介绍 Linux 的各种新的文件系统,包括 ReiserFS、XFS、JFS、GFS、ext3 和其它的文件系统。我要让您知道一些必要的实用知识,有了这些知识您才能开始使用这些文件系统。我的目标是帮助您尽可能地避免潜在的隐患;这就是说,我们将仔细地了解一下文件系统的稳定性、性能问题(或好或差)、您应该知道的任何的负面应用程序交互作用、内核与补丁的最佳搭配以及更多内容。您可以把这一系列的文章看成是这些下一代文件系统的“内幕指南”。
这就是准备好的内容。但是要开始这一系列工作,我还有一篇文章要脱离这个主题,用来为接下来的行程做准备。我将会涉及两个对于 Linux 开发社区非常重要的主题 — 日志和 ReiserFS 后的设计理念。日志是非常重要的,因为它是我们长期以来一直期待的技术,而现在终于出现了。在 ReiserFS、XFS、JFS、ext3 和 GFS 中都用到它。确切地理解日志是做什么的和为什么 Linux 需要它是非常重要的。即使您对日志已有所掌握,我还是希望我有关日志的介绍可以成为一个好的模型,以用来向其他人解释这项技术,或者作为一项惯例,以利于全世界的部门和组织开始向这些新的日志文件系统进行转变。这个过程通常是由“Linux guy/gal”开始的,就像您自己也会说服其他人应该这么做。
在这篇文章的后半部分,我们将看看 ReiserFS 后的设计理念。通过这么做,我们能够很好地掌握一个事实,那就是这些新的文件系统并不只是为了做同样的事比老的系统快一点。它们还允许我们用以前完全不可能的方法来处理事情。开发人员在阅读这一系列文章时应该牢记这一点。这些新的文件系统的能力将很可能对您今后的 Linux 软件开发工程的代码编写产生影响。
理解日志:元数据
正如您所了解的那样,文件系统的存在允许您储存、检索和操作数据。为了实现这一目的,文件系统需要保持一个内在的数据结构使得您的数据有组织并且便于访问。这一内部的数据结构(确切地说就是“关于数据的数据”)被称为元数据。就是这个元数据的结构为文件系统提供了其特定的身份和性能特征。
通常,我们并不直接和文件系统的元数据打交道。而是一个特别的 Linux 文件系统驱动程序为我们作相应的工作。Linux 文件系统驱动程序是专门用来操作复杂的元数据的。然而,为了使得文件系统驱动程序正常工作,有一个很重要的必要条件;它需要在某种合理的、一致的和没有干扰的状态下找到元数据。否则,文件系统驱动程序就不能理解和操作元数据,那么您也就不能存取文件了。
理解日志:fsck
这就引出了 fsck。当 Linux 系统启动时,fsck 启动并扫描系统的 /etc/fstab 文件中列出的所有本地文件系统。fsck 的工作就是确保要装载的文件系统的元数据是处于可使用的状态。大多数的时候是可使用的。当 Linux 关闭时,它仔细地把所有的缓冲区数据转送到磁盘,并确保文件系统被彻底卸载,以保证系统再次启动时能够使用。典型的就是,fsck 扫描那些将被装载的文件系统,确定它们已被彻底卸载,并做出合理的假设 — 所有的元数据都没有问题。
然而,我们都知道不时地会有一些意外发生,例如意想不到的电源故障或者系统挂起。当出现这些不幸的情况时,Linux 没有机会彻底卸载文件系统。当系统重新启动,fsck 开始扫描时,它会检测到这些没有彻底卸载的文件系统,并做出合理的假设 — 文件系统可能没有为 Linux 文件系统驱动程序准备好。这就很有可能导致元数据在某种情况下陷入困境。
所以,为了弥补这种情况,fsck 将开始彻底的扫描并且全面地检查元数据,修正这一过程中找到的任何错误。一旦 fsck 完成这样的工作,文件系统就可以使用了。尽管意想不到的电源故障或者系统挂起可能造成最近修改的数据丢失,但是由于元数据现在是一致的,文件系统就可以被装载和投入使用了。
fsck 的问题
迄今为止,为确保文件系统的一致性,这种方法可能听起来并不是个坏主意,但是却不是最佳的解决方案。问题出自于这样一个事实 — fsck 必须扫描文件系统全部的元数据,以确保文件系统的一致性。对所有的元数据做彻底的一致性检查是一项极为费时的工作。通常至少要花上好几分钟才能完成。更糟糕的是,文件系统越大,完成这个彻底的扫描所花费的时间就越长。这就是个大问题,因为当 fsck 做它自己事情的时候,您的 Linux 系统实际上就是被切断的,并且如果您有一个庞大数量的文件系统存储,您的系统可能就会花上半个小时或者更长的时间来执行 fsck。当然,在任务紧要的数据中心的环境里,也就是在系统正常运行极为重要的环境下,标准的 fsck 工作可能会造成破坏性的结果。幸运的是,有更好的解决方案。
日志
日志文件系统通过增加一个叫做日志的新的数据结构来解决这个 fsck 问题。这个日志是位于磁盘上的结构。在对元数据做任何改变以前,文件系统驱动程序会向日志中写入一个条目,这个条目描述了它将要做些什么。然后,它继续并修改元数据。通过这种方法,日志文件系统就拥有了近期元数据被修改的历史记录,当检查到没有彻底卸载的文件系统的一致性问题时,这个记录就唾手可得了。
可以这样来看待日志文件系统 — 除了存储数据(您的素材)和元数据(关于素材的数据)以外,它们还有一个日志。您可以称它们为元元数据(关于素材数据的数据)。
运作中的日志
那么,fsck 如何处理日志文件系统呢?实际上,通常它什么都不做。它只是忽略文件系统并允许它被装载。在快速地恢复文件系统到达一致性状态的背后,真正起作用的在于 Linux 文件系统驱动程序中。当文件系统被装载时,Linux 文件系统驱动程序查看文件系统是否完好。如果由于某些原因出了问题,那么就需要对元数据进行修复,但不是执行对元数据的彻底扫描(就像 fsck 那样),而是查看日志。由于日志中包含了按时间顺序排列的近期的元数据修改记录,它就简单地查看最近被修改的那部分元数据。因而,它能够在几秒钟时间内将文件系统恢复到一致性状态。并且与 fsck 所采用的传统方法不同,这个日志重放过程在大型的文件系统上并不需要花更多的时间。多亏了日志,数百 G 的文件系统元数据几乎能在瞬间恢复到一致性的状态。
ReiserFS
现在,我们来谈一谈 ReiserFS,它是我们将要研究的几个日志文件系统中的第一个。ReiserFS 3.6.x(作为 Linux 2.4 一部分的版本)是由 Hans Reiser 和他的在 Namesys 的开发组共同开发设计的。Hans 和他的组员们相信最好的文件系统是那些能够有助于创建独立的共享环境或者命名空间的文件系统,应用程序可以在其中更直接、有效和有力地相互作用。为了实现这一目标,文件系统就应该满足其使用者对性能和功能方面的需要。那样,使用者就能够继续直接地使用文件系统,而不必建造运行在文件系统之上(如数据库之类)的特殊目的层。
小文件的性能
那么,如何能使文件系统更加适应环境呢?Namesys 已经决定着眼于文件系统的一个方面,至少最初是 — 小文件的性能。通常,像 ext2 和 ufs 这样的文件系统在这一方面做的并不是很好,经常迫使开发人员转向数据库或者特别组织的处理来获取他们所需要的某种性能。随着时间的推移,这种“围绕问题进行编码”的方法怂恿了代码的膨胀和许多不兼容的特殊目的 API,这并不是好事情。
这儿有一个 ext2 如何鼓励这种编程的例子。ext2 很擅长存储大量大小在 20k 以上的文件,但是对于存储 2,000 个 50 字节的文件来说,它就不是一种很理想的技术了。当 ext2 必须处理非常小的文件时,不只是性能显著地下降,而且存储效率也同样下降,因为 ext2 是按 1k 或者 4k 的块来分配空间的(可在文件系统创建时设定)。
现在,常规的明智做法会提示您不应该在文件系统上储存这么多小的文件。而是应该存储在某种运行在文件系统之上的数据库里。作为对这种说法的回应,Hans Reiser 指出无论何时您需要在文件系统的顶上建立一层,那就意味着文件系统不满足您的需要。如果文件系统满足您的需要,那么您首先就要避免使用特殊目的的解决方案。这样就可以节省开发的时间,并消除代码膨胀。这些代码可能是在您手动处理自己的个人存储器或者缓冲机制时,或者与数据库的某个库交互作用过程时所产生的。
理论上是这样。但是在实际运用中,ReiserFS 的小文件性能会是如何的好呢?好得让人吃惊。实际上,当处理小于 1k 的文件时,ReiserFS 大概要比 ext2 快 8 到 15 倍!更妙的是,这些性能提高并不以其它文件类型的性能损失为代价。通常,ReiserFS 几乎在各个方面都优于 ext2,但是在处理小文件时才真正体现出了其闪光点。
ReiserFS 技术
那么 ReiserFS 是怎样提供如此出色的小文件性能的呢?ReiserFS 使用了特殊的优化 b* 平衡树(每个文件系统一个)来组织所有的文件系统数据。这为其自身提供了非常不错的性能改进,也能够减轻文件系统设计上的人为约束。例如,现在一个目录下可以容纳 100,000 个子目录。另一个使用 b* 树的好处就是 ReiserFS 能够像大多其它的下一代文件系统一样,根据需要动态地分配索引节,而不必在文件系统创建时建立固定的索引节。这有助于文件系统更灵活地适应其面临的各种存储需要,同时提供附加的空间有效率。
ReiserFS 有许多特征是特别针对提高小文件的性能的。和 ext2 不同,ReiserFS 并不固定地以 1k 或者 4k 的块分配存储空间,而是分配所需要的精确尺寸。而且 ReiserFS 也包括了以尾文件为中心的特殊优化 — 尾文件是指那些比文件系统块小的文件及文件结尾部分。为了提高性能,ReiserFS 能够在 b* 树的叶子节点存储文件,而不是把数据存储在磁盘的其它地方再指向它。
这做了两件事。第一,它显著地提高了小文件的性能。由于文件数据和 stat_data(索引节)信息是紧挨着存储的,它们通常能被同一次磁盘 IO 操作所读取。第二,ReiserFS 能够压缩尾文件,节省大量磁盘空间。实际上,带有尾文件压缩功能(默认)的 ReiserFS 文件系统可以比同等的 ext2 文件系统多存储 6 个百分点的数据,这就其自身来说是令人惊叹的。
然而,由于在文件被修改时,尾文件压缩迫使 ReiserFS 重装数据,这就导致了性能上的轻微折损。鉴于这个原因,ReiserFS 尾文件压缩可以被关掉,允许系统管理员在速度与空间有效率上做出选择,或者牺牲一些存储能力来换取更高的速度。
ReiserFS 确实是一个非常出色的文件系统。在我的下一篇文章中,我将会指导您在 Linux 2.4 下完成 ReiserFS 安装的全过程。我们还将仔细地看一看性能调整,应用程序交互作用(和怎么围绕他们工作)以及使用的最佳内核等等。
参考资料
Namesys 网页正是更多地了解 ReiserFS 的地方。
要想了解当前更为深入的 ReiserFS 信息,ReiserFS 邮件列表是一个极好的资源。也一定要查看 ReiserFS 邮件列表档案。
您可以在 Juan I. Santos Florido 的 Linux Gazette 日志文件系统的回顾中,发现对于 UFS、ext2、ReiserFS 和更多文件系统中元数据的不同之处的深入探讨。
Jedi 的 ReiserFS/Qmail tuning page 中包含了许多对于 qmail 使用者来说很好的信息。也请一定查看 ReiserSMTP — Jedi 的 drop-in qmail 组件集,它提供了令人注目的更高 qmail 性能。
Linux 每周新闻是紧跟着最新内核发展的非常好的参考资料。
请阅读在 developerWorks 上的 Steve Best 的 JFS 概述。
请阅读一下在 developerWorks 上的 JFS 基础教程。
关于作者
Daniel Robbins 居住在新墨西哥州的 Albuquerque。他是 Gentoo Technologies, Inc. 的总裁兼 CEO,Gentoo Linux(用于 PC 的高级 Linux)和 Portage 系统(Linux 的下一代移植系统)的创始人。他还是 Macmillan 书籍 Caldera OpenLinux Unleashed、SuSE Linux Unleashed 和 Samba Unleashed 的合作者。Daniel 自二年级起就与计算机结下不解之缘,那时他首先接触的是 Logo 程序语言,并沉溺于 Pac-Man 游戏中。这也许就是他至今仍担任 SONY Electronic Publishing/Psygnosis 的首席图形设计师的原因所在。Daniel 喜欢与妻子 Mary 和新出生的女儿 Hadassah 一起共度时光。可通过 drobbins@gentoo.org 与 Daniel 联系。