================================
(接上文《架构设计:系统存储(3)——块存储方案(3)》)
在上文6-1小节中介绍的Ext文件系统结构主要适用于Ext2和Ext3文件系统,这两个版本的Ext文件系统在数据组织结构上基本上没有什么变化。Ext3文件系统相对于Ext2文件系统所做的主要优化在数据写入策略上。
Linux操作系统为了加快I/O操作过程,当有文件需要写入文件系统时Linux操作系统并不会立刻将文件数据实际写入data block,而是存储到一个内存区块中。如果您通过top命令或者Free命令,就可以看到这个名叫cache memory的内存区块。
[root@lab-backup ~]# free
total used free shared buffers cached
Mem: 3805272 3662628 142644 508 1758376 1491128
-/+ buffers/cache: 413124 3392148
Swap: 3948540 0 3948540
无论是Ext2文件系统还是Ext3文件系统又或者是Ext4文件系统,写入cache memory区块的这个过程是不会改变的。以上示例效果中还有一个叫做buffers memory的内存区块,这个区块缓存了文件系统的部分Inode信息,这样保证了操作系统不会随时到文件系统上寻找Inode——优化文件系统的读性能。cache memory区块和buffers memory区块由操作系统自行管理,它们只会使用当前没有被应用程序占用的空闲内存。当应用程序请求新的内存区块且空闲内存不够时,操作系统会释放部分cache memory区块或者buffers memory区块。后文我们讲解Linux下的Page Cache技术时,还会对这部分只是进行详细讲解。当cache memory区块写满或者到达一个等待时间后,操作系统就会正式开始向文件系统写数据了。
在Ext2文件系统中,完成文件写入的过程可以简要的进行如下描述:首先文件系统会在收到文件写入请求后根据算法寻找一个还没有使用的Inode,这个算法过程根据不同文件系统小版本和Linux内核版本的不同而有所变化,但寻找原则都是一样的,即尽可能为文件寻找连续的inode和data block。上文已经提到Ext文件系统中,每一个block group都有Block bitmap区域和Inode bitmap区域分别用于记录block group中的block和Inode的使用情况。在寻找Inode的这个步骤中,block group的Block bitmap、Inode bitmap区域还不会被写入任何变化,block group的Group description table区域也不会被写入任何变化。
接下来Ext2文件系统就要向硬件层正式写入数据了,这个步骤还包括建立Inode和data block的关联信息。最后当文件系统相对空闲的情况下,文件系统才会更新block group中的Block bitmap、Inode bitmap和Group description table区域。正常情况下这种操作过程并没有太大的问题,因为文件系统随时都清楚哪些Block bitmap、Inode bitmap被真正使用了,哪些Block bitmap、Inode bitmap是被使用但还没有来得及更改状态。当文件系统正常关闭时Ext2文件系统会设置一个校验标记Valid bit=1,表示本次文件系统的操作正常结束。
但是如果当文件系统因为各种原因异常关闭时(例如断电)这个标记的值就为0,那么问题就来了。因为哪些已经被使用但还没有来得及被标示的Block bitmap、Inode bitmap区域,和真实的使用情况就存在误差了。虽然操作系统下次启动时会对整个文件系统进行扫描试图恢复操作(主要目的是恢复Block bitmap、Inode bitmap和真实事情情况的一致性),但是操作系统并不保证一致性被全部恢复。这样看来Ext2文件系统的写入过程至少存在一下几个问题:
由于data block块的写入操作和Block bitmap、Inode bitmap区域的更新过程是分开进行的,所以当系统异常关闭时Ext2文件系统并不能保证Block bitmap、Inode bitmap的状态和真实的block使用情况完全一致。所以才会有系统重启时试图恢复磁盘一致性的修复操作。
Ext2文件系统对于大文件的读写性能并不好,这是因为当文件特别大时,Ext2文件系统会启用三级间接指针和四级间接指针建立Inode和data block的联系。虽然当data block size为4KB时单个文件的大小可达4TB,但是因为存储大文件时会启用二级、三级甚至四级间接指针,这大大增加了文件系统上的索引查找时间。所以这种多级索引的思路除了可以增加单个文件容量外,对提升大文件的读写性能实际上并没有太多帮助。
另外Ext2文件系统在向data block写入文件数据时,将以data block size(默认为4KB)为单位依次向硬件层提交数据,这就是为什么在其它设置不变的情况下,如果将Ext2文件系统的data block size格式化为8KB,会增加一定的磁盘读写性能的原因。
以上小节中提到的Ext2文件系统的明显问题中,最严重的应该还是文件系统异常情况下Block bitmap、Inode bitmap可能出现的一致性问题。所以Ext3文件系统在基本保持Ext2文件系统组织结构的前提下,使用索引日志的思路来解决Ext2文件系统上的数据一致性问题。
Ext3文件系统又被称为日志文件系统,它在Ext2文件系统的基础上做的主要改动就是,在正式写入data block数据并建立Inode索引前,通过在磁盘上的某块固定位置写入一段日志数据的方式建立这两个操作过程的关系,并根据后续操作进行日志数据的保留/删除,以达到保持操作一致性的目的。这样一来,即使文件系统上一次异常关闭,当文件系统再次启动时也不需要再进行整个文件系统Inode和data block扫描了,只需要重新加载日志数据文件系统就可以知道上一次异常关闭时还有哪些Block bitmap、Inode bitmap没有处理完。
Ext3文件系统支持三种日志模式,他们在数据一致性和I/O性能上有所区别:
journal日志模式
在这种模式下,当文件系统正式开始进行磁盘操作前会在磁盘的上专门的日志区域创建这个文件的副本,包括这个文件的Inode和data block完整信息,副本创建完成后才会按照正常的写入过程进行文件写入。当写入操作正常完成后,文件系统会删除日志区域的文件副本。这样一来当文件系统发生异常并重启后,e2fsck检测程序会扫描日志区域中的副本:如果发现文件副本本身就不完整,则会丢弃这部分副本。如果发现文件副本是完整的,则会继续完成正式文件的写入过程,最后删除文件副本。很显然journal日志模式会增加单个文件的磁盘操作次数,所以journal日志模式是三种日志模式中速度最慢的一种。但是journal日志模式却可以做到最完整的数据一致性要求。
ordered日志模式
ordered日志模式是Ext3/Ext4文件系统默认的日志模式。这种模式比 journal日志模式快了许多,因为ordered日志模式下Ext文件系统的日志区域并没有真正记录文件的真实数据,不会发生一个文件的多次读写过程。当文件系统为新文件确定了Inode和block区域后,这些Inode、Block bitmap、Inode bitmap等索引信息将会首先保存到文件系统的日志区域,并形成一个事务单位。当文件数据被完整写入磁盘对应的block后,文件系统才会将日志区域的Inode信息和block信息提交到对应的block group中,完成整个写入过程。当文件系统发生异常并重启后,e2fsck检测程序会扫描日志区域中的副本:如果发现还有事务单位没有被提交,那么磁盘上对应的block位置上的信息将被清除,以保持文件信息一致性。
writeback日志模式
这是一种异步日志模式,文件系统的日志区域虽然也记录将写入磁盘的新文件的Inode、Block bitmap、Inode bitmap等索引信息。但是和ordered日志模式不同的是,这些日志信息记录过程和文件数据的写入过程没有先后关联,并且也不存在“提交”的概念。当文件系统发生异常并重启后,e2fsck检测程序也不会按照日志区域的数据状态进行一致性修复。writeback日志模式在大多数情况下能够提供最佳的Ext3/Ext4文件系统性能,因为日志功能几乎是关闭的。
从以上三种Ext3文件系统日志模式的简述中,可以发现的Ext3日志并不保证数据不丢失。实际上保证数据不丢失并不是Ext3日志的目标,而保证数据一致性才是Ext3日志的主要目标。为了达到这个目标,日志数据甚至会主动丢弃无法复原的副本数据。
本小节介绍如何查看和设置Ext3/Ext4文件系统的日志模式。首先为了确定当前文件系统是否开启了日志模式,可以使用dumpe2fs命令进行查看:
# dumpe2fs /dev/sdb2
dumpe2fs 1.41.12 (17-May-2010)
Filesystem volume name: <none>
Last mounted on: <not available>
Filesystem UUID: 0e94b563-8348-4056-8770-67fa34e2b903
Filesystem magic number: 0xEF53
Filesystem revision #: 1 (dynamic)
Filesystem features: has_journal ext_attr resize_inode dir_index filetype
...... Journal backup: inode blocks Journal features: (none) 日志大小: 128M Journal length: 32768 Journal sequence: 0x00000001 Journal start: 0 ......
以下的block group信息可以忽略
可以看到Filesystem features选项中有一个has_journal关键信息标识,这表示当前文件系统已经开启了日志功能。如果没有看到这个标记,则说明文件系统本身还没有开启日志功能——这种情况下Ext3文件系统就和Ext2文件系统没有太大区别了。
以下命令可以开启Ext3/Ext4文件系统的日志功能:
# tune2fs -O has_journal /dev/sdb2
tune2fs 1.41.12 (17-May-2010)
Creating journal inode: done
以下命令可以关闭Ext3/Ext4文件系统的日志功能:
# tune2fs -O ^has_journal /dev/sdb2
tune2fs 1.41.12 (17-May-2010)
但必须注意这并不表示指定了具体的日志模式,在开启了文件系统日志功能的情况下读者可以在使用mount进行具体挂载时指定日志模式。如下所示:
mount -o data=journal /dev/sdb2 /mnt/hgfs/
以上命令的data参数部分可以换成ordered、writeback和journal,代表文件系统支持的三种日志模式。设置完成后文件一同也完成了挂载。但是怎么检查日志模式设置是否成功呢?读者可以通过dmesg命令查看Linux系统的内核日志,在日志的最后一行会有最近一次的挂载信息,类似如下:
# dmesg
......
EXT3-fs (sdb2): using internal journal
EXT3-fs (sdb2): mounted filesystem with journal data mode
SELinux: initialized (dev sdb2, type ext3), uses xattr
可以看到内核日志信息的最后一行信息说明最近完成的内核变动操作,是按照journal日志模式挂载sdb2分区。当然内核日志信息包含了很多无用的信息,读者还可以通过以下命令索引出需要查看的信息:
# dmesg | grep -B 1 "mounted filesystem"
...... sd 2:0:0:0: [sda] Attached SCSI disk EXT4-fs (sda2): mounted filesystem with ordered data mode. Opts: -- Microcode Update Driver: v2.00 <[email protected]>, Peter Oruba EXT4-fs (sda1): mounted filesystem with ordered data mode. Opts: -- EXT3-fs (sdb2): using internal journal EXT3-fs (sdb2): mounted filesystem with journal data mode ......
当然最终我们还是要实现磁盘的永久挂载,这是就需要更改Linux操作系统中的/etc/fstab文件了。如果读者使用的是文件系统默认的ordered日志模式,则不需要在/etc/fstab文件中进行额外的设置。但如果不是这样的话,读者在设置/etc/fstab文件时,就要在其中的options列说明文件系统使用的日志模式。类似如下所示:
# vim /etc/fstab
...... /dev/sdb2 /mnt/hgfs ext3 data=journal 0 0 ......
上一节我们讨论了Ext3文件系统相对于Ext2文件系统最大的改进点——日志模式。但是Ext2文件系统中另外一个问题还没有做太多调整:因为存储大文件时Ext2/Ext3文件系统会启用二级、三级甚至四级间接指针建立Inode和data block的联系,这样的做法会降低文件系统上对大文件的读写能力。
Ext4文件系统的细节文章就不再过多介绍了,因为系统存储这个专题到到现在已经从最底层硬件设备开始到阵列结构再到操作系统上的文件系统进行了说明,相信读者已经理解了为什么这种传统的存储方案被称为块存储方案了。但是真正和软件架构有关的知识却还一点都没有介绍。这显然偏离了本专题最初规划。
对Ext4文件系统有兴趣的读者可以继续参考Ext官方文档(https://kernelnewbies.org/Ext4) ,从下文开始我们将转入普遍搭建在块存储方案之上的关系型数据库的相关知识介绍(主要为MySQL数据库),包括影响关系型数据库性能的重要因素、如何进行关系型数据库集群的搭建。