Solaris中的logging功能的应用
在Solaris7及其以后版本的系统中有一种称为logging的功能。它不但易于安装和使用,并且对于数据安全非常有用。
UFS是存在于Sun工作站的几乎所有硬盘分区(swap等个别分区除外)上的一种标准的文件系统类型。而logging功能是UFS文件系统的一个挂接选项,它可以被设置在包括/在内的各个硬盘分区上。
Solaris的UFS logging通过使用系统中的空白数据块来工作。所有对文件系统数据(metadata,或称为元数据)的修改都被写在这些空白的区域。这些Metadata包括目录和inode信息,不包括文件中的数据本身。比如创建文件时,目录结构被修改并且系统为这个新文件分配一个新的inode。以上这些行为被写入做logging的空间中。一旦数据的修改行为被写入做logging的区域,系统就可以接着对文件系统做其它的操作了。在后台,存在于logging中的信息将被同步到文件系统中,并自动更新相应的目录和I节点,最终完成文件系统的操作。数据也陆续被写入硬盘。因此这种做logging并在后台写入数据,比通过随机的I/O访问直接对分布在硬盘上的各种管理信息进行修改的方式速度要快得多。用来做logging的空间的大小取决于文件系统的大小。每1GB磁盘分区空间的logging空间为1MB,最多不超过64MB。这部分logging空间被循环使用:当log空间即将装满时,暂停新的metadata数据写入,直至log空间被清空。当log中记录的关于文件系统的修改都被应用于文件系统后,那部分空间又重新可以作为log空间来存放新的metadata数据了。
通常对于UFS来说,如果操作系统在任何文件系统操作中崩溃,整个文件系统都需要用fsck命令做一致性检查。这个命令的执行可能需要几分钟的时间,因为它需要检测所有的metadata和文件的数据以确认文件系统的完整性:包括当前已经用的空间、未用的、inode的数量等,修复其中不一致的地方。出现比较大的问题时还需要人工干预。在做检查的过程中有可能会丢失文件,甚至目录。这决定于crash发生时,该操作进行到了哪种程度。如果采用logging功能,情况就完全不同。因为metadata的修改首先被写在log空间而不是文件系统中。如果系统崩溃,对文件系统一致性的检测可以仅仅限于log中记录的那部分,这样会更简单、更有效。系统检查logging的数据,以决定在上一次的文件系统中,哪种修改已经做过了,哪种修改即将做,哪种修改正在做, 做过的和即将做但还没有做的操作被系统从log中删掉, 而那些做了一部分的会被接着做完或完全取消掉。如果在log中记录了足够的数据来完成这一操作,该操作会被继续完成。否则,这种改变会被取消。熟悉数据库操作的用户会发现这和数据库软件中的事务处理过程非常相似。最终的结果是:文件系统能够最大限度地保持一致,不需要进行彻底的文件系统检测,整个文件系统检测过程只需要花几秒钟时间。从Solaris 7开始, mount命令和/etc/vfstab文件中也有了一个新的logging选项。
为了验证logging选项对系统性能的贡献,我们做一个脚本文件,它要创建1000个目录。这种操作将对系统中的metadata的处理带来非常大的压力。实验在一台运行Solaris7的Ultra 5机器上进行:
# more logging-test
#!/bin/ksh
# Test ufs logging performance
# Get to the right place and make a test directory
cd /big
mkdir test
# Create 1000 directories
integer i=0
while ((i < 1000))
do
mkdir test/test${i}
i=i+1
done
# chmod a+x logging-test 给文件加上执行权限
第一次做实验时不采用logging选项(Solaris 7和8的文件系统缺省状态下都不采用这种选项)。
# time ./logging-test 用此命令测一下整个执行时间
real 27.7
user 2.0
sys 4.9
# time rm -rf /big/test
real 8.0
user 0.0
sys 0.3
结果创建和删除目录共需要35.7秒时间。第二次采用logging选项,再做一次测试:
# umount /big
# mount -o logging /big
# time ./logging-test
real 13.2
user 1.7
sys 5.4
# time rm -rf /big/test
real 0.8
user 0.0
sys 0.2
同样的命令在采用UFS logging以后只需要14秒的时间,性能提高非常明显。下一个测试更有趣。不采用logging,并在上面的脚本执行过程中关机,那么下一次启动时,系统要求进入单用户状态手工执行fsck来修复系统,在修复过程中也报了很多错。修复了以后,系统可以引导起来。采用了logging功能后,同样的实验过程却得到了令人鼓舞的结果:系统仅仅提示:
/dev/c0t1d0s3: is logging
没有其它的报错信息给出。
但是UFS logging最初会有一些bug,在采用UFS logging之前,需要打最新的系统核心patch,并且最好在另一个非生产环境进行测试。
还有另一种比较新的而且很有用的mount选项:noatime。如果没有noatime选项,每个文件每次被访问,它的I节点中的访问时间的值都会被更新。这样,用ls ?lu命令可以看出文件最近一次被“读”的时间。但是有些情况下我们并不关心文件什么时候被读过,比如Web server 的内容,但是他们增加很多的IO负载,从而影响性能。使用noatime会减少访问时间被更新的频率,它使系统只有在该文件的其它I节点属性同时修改时才更新文件的访问时间。在我们不关心访问时间的文件系统中,这不会对系统造成什么损害。