(接上文《架构设计:系统存储(2)——块存储方案(2)》)
目前磁盘阵列设备被广泛应用在从民用级计算到工业级计算的各个基础领域,本小节的内容就带各位读者进行一些概要性了解。
最廉价的,也是在民用级市场上最普遍的做法,是将阵列控制器直接集成在主板上。RAID 0、RAID 1、RAID 5、RAID 10等阵列组织结构都可以在这种集成方式下提供支持。这些主板的价格可以做得很亲民,但是这样的阵列控制器集成方案也存在比较明显的问题:支持的磁盘数量有限制,总的I/O吞吐性能也存在瓶颈。
另一种做法是将阵列控制器至于计算机以外,民用级市场和企业级市场上也经常使用这种集成方式,并且效果要好得多,因为至少从可集成的磁盘数量上来说就比上一种做法要好得多。但是由于制造成本的原因,这些外挂的磁盘阵列盒一般还是采用USB3.0等接口进行数据传输,所以吞吐性能上基本不会有太大提升:
企业级和工业级项目中,进行磁盘阵列方案实施时更多使用磁盘阵列柜和光纤接口。这样可以缓解磁盘横向扩展的问题和数据传输吞吐性能的问题。例如EMC提供的大型磁盘阵列设备:
通过以上1-5节的内容,我们向读者介绍了位于块存储方案最底层的磁盘设备和阵列控制设备的工作原理和具体应用。特别是阵列控制设备,目前大量应用在商业级系统和工业及系统中,这样的存储方案也是应用最成熟的方案。那么操作系统为了抽象化这些底层设备的控制,就需要在操作系统层面组织一个管理文件数据逻辑地址的统一结构,以便向上层开发者屏蔽硬件操作细节。这样的管理结构称为文件系统。
目前主流的文件系统包括windows下的NTFS文件系统、Linux下的EXT系列文件系统(管理规则已升级到EXT4)、XFS文件系统和Btrfs文件系统。由于本专题的知识体系全部基于Linux操作系统,所以我们不会对NTFS文件系统做过多介绍。在本文中我们主要介绍两种Linux下的文件系统:EXT系列文件系统和XFS文件系统。
EXT文件系统英文全称:Extended file system。最初的EXT文件系统于1992年发布,用于替换之前使用的MINIX文件系统。经过多年的发展,目前EXT文件系统已经发展出4个版本,Ext1、Ext2、Ext3和Ext4。这些不同版本的文件系统中,虽然一些结构细节发生了变化(例如采用更快的Data blocks查找方式、采用更宽的索引位等),但这几个版本中提现的文件系统设计思想却没有太大的改变。
本节将从一个统一的文件系统数据组织结构开始讲起,首先说明结构中重要区块的作用,然后说明区块间的关联关系并推导一些关键的数据计算公式,最后再阐述几个Ext文件系统版本的重要改进。
(Ext文件系统主要结构图)
上图描述了Ext文件系统主要结构。就如上文描述的那样,不同的Ext文件系统版本对以上结构都有一定的调整,但是文件系统管理结构中的重要区块的作用却没有发生什么变化,所以不会影响我们下文的讲解。首先需要说明,操作系统层面建立文件系统的单位都是磁盘分区,也就是说操作系统可以在一个物理磁盘上或者一个阵列管理设备上建立多种不同的文件系统。很多第三方分区工具都可以帮助开发人员/运维人员完成物理磁盘的分区操作。但是有一个问题需要特别说明一下:Linux系统下自带的fdisk工具只能支持2TB的最大分区容量,如果需要分割出大于2TB容量的分区,则需要使用Linux操作系统下的另一个工具parted,其根本原因是fdisk工具建立的是MRB分区表,而parted工具可以建立GPT分区表。
Ext系列文件系统的组织结构都是在进行格式化的时候就基于磁盘分区建立完毕的,以下示例脚本是针对一个名叫sdb1的磁盘分区成功建立Ext3文件系统后的显示信息。
[root@localhost ~]# mkfs.ext3 /dev/sdb1
mke2fs 1.41.12 (17-May-2010)
Filesystem label=
OS type: Linux
Block size=4096 (log=2)
Fragment size=4096 (log=2)
Stride=0 blocks, Stripe width=0 blocks
1310720 inodes, 5241198 blocks
262059 blocks (5.00%) reserved for the super user
First data block=0
Maximum filesystem blocks=4294967296
160 block groups
32768 blocks per group, 32768 fragments per group
8192 inodes per group
Superblock backups stored on blocks:
32768, 98304, 163840, 229376, 294912, 819200, 884736, 1605632, 2654208,
4096000
Writing inode tables: done
Creating journal (32768 blocks): done
Writing superblocks and filesystem accounting information: done
以上脚本信息中有几个关键点需要读者注意,这几个关键点将和后文叙述的信息形成对照:
Block size=4096和First data block=0:前一个信息说明Ext3文件系统中采用的每一个block的单位大小为4KB;后一个信息说明第一个Data block(Data block用于“真正”存储文件数据)的起始号。
Maximum filesystem blocks=4294967296:这个信息并不是说文件系统所在磁盘分区的最大block数量,而是说Ext3文件系统所支持的最大block数量。如果按照Block size=4096进行计算,那么4294967296 * 4096 = 16TB。这个值就是当block size为4KB时,Ext3文件系统理论上支持的最大容量(但实际上是无法达到这个容量的)。
160 block groups:这个信息表示Ext3文件系统被分为160个block group。下文中将进行block group的详细介绍。这刚好和该Ext3文件系统的总容量是对应的:block groups * blocks per group * Block size = 160 * 32768 *4096 = 20,971,520 Byte = 20GB。
32768 blocks per group表示每一个block group组中所包含的block数量,这里的block并不单单指Data block,还包括block group中用来描述索引的inode table区域、可能预留的GDT区域、 block bitmap、inode bitmap等信息区域。
8192 inodes per group:这个信息表示了每一个block group中所包含的inode个数。inode个详细结构将在后文中进行介绍
Superblock backups stored on blocks:Superblock区域存储了Ext文件系统中非常重要的信息,这部分信息在一个Ext文件系统中有多个备份。这个信息向显示文件系统完成格式化后,有哪些block存储了Superblock区域的备份。
Creating journal (32768 blocks):journal日志区域和日志区域所占用的block数量,这个区域是Ext3、Ext4两种文件系统所独有的,Ext2文件系统中没有这个区域。关于journal日志区域的作用后文也会进行详细描述。
上图(Ext文件系统主要结构图)中我们在sdb1磁盘分区上建立的Ext文件系统,它的最顶层由若干个block group结构组成。他们在文件系统完成格式化的时候就被预先分配好了,所以如果您使用dumpe2fs命令查看某一个ext分区的分区状态信息,就可以看到类似以下的信息(返回结果中段):
# 已省去大量状态描述信息
[root@lab-backup ~]# dumpe2fs /dev/sdb1
...... dumpe2fs 1.41.12 (17-May-2010) ......
Filesystem flags: signed_directory_hash
Default mount options: (none)
Filesystem state: clean
Errors behavior: Continue
Filesystem OS type: Linux
Inode count: 1310720
Block count: 5241198
Reserved block count: 262059
Free blocks: 5114876
Free inodes: 1310709
First block: 0
Block size: 4096
Fragment size: 4096
...... Group 157: (Blocks 5144576-5177343) Block bitmap at 5144576 (+0), Inode bitmap at 5144577 (+1) Inode table at 5144578-5145089 (+2) 32254 free blocks, 8192 free inodes, 0 directories Free blocks: 5145090-5177343 Free inodes: 1286145-1294336 Group 158: (Blocks 5177344-5210111) Block bitmap at 5177344 (+0), Inode bitmap at 5177345 (+1) Inode table at 5177346-5177857 (+2) 32254 free blocks, 8192 free inodes, 0 directories Free blocks: 5177858-5210111 Free inodes: 1294337-1302528 Group 159: (Blocks 5210112-5241197) Block bitmap at 5210112 (+0), Inode bitmap at 5210113 (+1) Inode table at 5210114-5210625 (+2) 30572 free blocks, 8192 free inodes, 0 directories Free blocks: 5210626-5241197 Free inodes: 1302529-1310720 ......
dumpe2fs的主要作用就是返回指定分区上建立的文件系统中super block的档案系统信息和每个block group组的信息。可以看到以上的命令显示了“/dev/sdb1”的分区中一共有160个block group,并且至少从第157个block group开始,其中的inode记录和block记录都是空闲的。
在以上命令中指定的目标分区“/dev/sdb1”采用Ext3文件系统进行格式化,所以读者看到的每一个分区的inode数量和block数据和我们后文的讲解在数值上可能会有一些出入,但是不会影响去理解Ext系列文件系统管理文件数据的组织思路。那么每一个block group中包括的数据结构主要还有:
Super block从字面上可以理解成“超级块”,其中存储了文件系统非常关键的信息用于向使用者描述当前文件系统的状态,例如block与inode的使用情况(总量和已使用量)、每个inode的大小、文件系统挂载点等等信息(后文会给出重要信息项的介绍)。并不是所有block group中都有Super block,实际上一个Ext文件系统中,只有一个唯一的Super block信息区域,但为了保证Super block不会丢失,所以会有一部分block group对完整的Super block信息进行备份,这就是为什么我们在上一小节中,格式化成功后的返回信息中会有一个“Superblock backups stored on blocks”信息。以下是dumpe2fs命令针对“/dev/sdb1”分区上的文件系统所打印的另一段返回信息,这些信息都记录在super block区域中:
[root@lab-backup ~]# dumpe2fs /dev/sdb1
dumpe2fs 1.41.12 (17-May-2010)
......
Filesystem flags: signed_directory_hash
Default mount options: (none)
Filesystem state: clean
Errors behavior: Continue
Filesystem OS type: Linux
Inode count: 1310720
Block count: 5241198
Reserved block count: 262059
Free blocks: 5114876
Free inodes: 1310709
First block: 0
Block size: 4096
Fragment size: 4096
Reserved GDT blocks: 1022
Blocks per group: 32768
Fragments per group: 32768
Inodes per group: 8192
Inode blocks per group: 512
......
Reserved blocks uid: 0 (user root)
Reserved blocks gid: 0 (group root)
First inode: 11
Inode size: 256
Required extra isize: 28
Desired extra isize: 28
Journal inode: 8
Default directory hash: half_md4
Directory Hash Seed: bd0a2065-d9ff-4abe-ad05-ded757287a0d
Journal backup: inode blocks
Journal features: (none)
Journal size: 128M
Journal length: 32768
Journal sequence: 0x00000001
Journal start: 0
......
为了保证文件系统在磁盘部分扇区出现物理问题的情况下还能正常工作,就必须保证文件系统的super block信息在这种情况下也能正常访问。所以一个文件系统的super block会在多个block group中进行备份,这些super block区域的数据保持一致。这里我们还需要对其中重要的参数项进行解释,以便帮助后文描述block group的其他区域:
Inode count:该参数表示在本文件系统中所有Inode的总数,这些Inode分布于不同的block group中,存在于这些block group的Inode Table区域。在后面的文章内容中,我们会详细讨论Inode区域的结构。
Free inodes:该参数说明当前文件系统中还有多少可用的Inode区域。
Inodes per group:该参数说明文件系统的每个block group中存在多少个Inode信息。
Inode size:每个Inode占用的存储空间大小,在以上显示的文件系统信息中每个Inode占用的大小都是256字节。注意,Inode的总数量、单位Inode所占用的存储空间、每个block group所拥有的Inode数量都是在文件系统格式化的时候就完成了初始化,所以无论当前的Inode是否已经有对应的文件,这个Inode都会占用256字节的空间。在以上显示的文件系统信息中,总共有1310720个Inode,每个Inode又占用256字节的空间,所以文件系统中所有Inode占用的空间为:1,310,720 * 256字节 = 335,544,320字节 = 320MB。
Block count:该参数表示在本文件系统中所有block的总数。
Free blocks:该参数说明当前文件系统中还有多少可用的block数量。一定要注意这些free block并不是全部用于记录文件数据的,例如,根据Super block中的信息一个block group要占据32768个block(128MB),其中就包含了后文我们要说明的各种数据区域,甚至包括inode所使用的block。所以我们常说的Ext3文件系统16TB的总容量实际上只是理论值,因为一个真实大小为100MB的文件在Ext文件系统上不仅仅只会使用100MB的空间进行记录。
Block size:该参数表示每个block所占用的磁盘空间。Ext2/Ext3文件系统中,该参数的默认值为4096(即4KB空间),并且这个参数可以在文件系统格式化的时候进行更改。那么从以上显示的文件系统中信息中,总共有5,241,198个block,所以整个文件系统可用的block总大小为5,241,198 * 4096字节 = 21,467,947,008字节 = 20TB
Blocks per group:该参数表示每个block group所占用的block数量。Ext文件系统中,该参数的默认值为32768。就像上文已叙述的那样,这里的32768个block包括了block group的所有结构区域:如果该block group拥有备份的Super block,那么Super block会占用1个block、Group description table占用1个block、Block bitmap占用1个block、Inode bitmap占用1个block、Inode table占用512个block(其中可能有8192个Inode也可能有16384个Inode),剩下的block的使用情况根据Ext文件系统的版本不一样而有所区别,但是大部分负责记录文件数据。
这个区域的信息描述了当前这个block group中的其它数据区域的所在位置和使用情况,包括后面要介绍的block bitmap的起始位置、inode bitmap的起始位置、inode table的位置和使用情况以及blocks的使用情况。每一个block group的Group description table都在block group的状态发生变化时一同变化。实际上各位读者已经看过了Group description table的描述信息,就是上文6-1-1小节给出的命令返回示例中所显示的另一段信息:
...... Group 159: (Blocks 5210112-5241197) Block bitmap at 5210112 (+0), Inode bitmap at 5210113 (+1) Inode table at 5210114-5210625 (+2) 30572 free blocks, 8192 free inodes, 0 directories Free blocks: 5210626-5241197 Free inodes: 1302529-1310720 ......
block group中的Block bitmap区域占用了4096字节(1个block),它用于帮助block group记录哪些block已经使用哪些没有使用。那么Block bitmap区域是如何完成这个工作任务的呢?Block bitmap区域的每一个bit都记录本block group中的一个block的使用情况,0表示对应的block还没有使用,如果为1则表示对应的block已被使用。既然Block bitmap区域占用了4096字节,就表示block bitmap一共有4096 * 8 = 32768 bit,也就意味着一个block group中最多有32768的block。这刚好和Super block中描述的“Blocks per group”一致。我们来具体看一个Block bitmap中的记录示例:
11110011 01010100 11101011 00000101 00000101 11100011
......
以上Block bitmap区域中的数据表示:在这个block group中,block区域第0个block已经被使用了,第1个block已经被使用了。。。第4个block还没有被使用。。。第12个block还没有被使用。。。第30个block还没有被使用。
Inode bitmap的作用是记录block group中Inode区域的使用情况,Ext文件系统中一个block group中可以有16384个Inode,代表着这个Ext文件系统中一个block group最多可以描述16384个文件。在本文6-1-1小节中所给出的Ext3文件系统中,每个block group中有8192个Inode(“Inodes per group”参数描述)。每个Inode bitmap区域本身需要占据4096字节,其描述block group中Inode区域使用情况时所使用的思路和Block bitmap区域使用的思路相似,不同的是Inode bitmap区域中所使用的4096字节中未对应Inode区域的部分将使用“1”进行填充。
在Ext2/Ext3文件系统中,每个文件在磁盘上的位置都由文件系统block group中的一个Inode指针进行索引,Inode将会把具体的位置指向一些真正记录文件数据的block块,需要注意的是这些block可能和Inode同属于一个block group也可能分属于不同的block group。我们把文件系统上这些真实记录文件数据的block称为Data blocks。我们将在下文中详细介绍Inode的组织结构。
Ext2/Ext3文件系统中,采用Inode指针和Data block地址进行直接/间接关联的方式记录文件数据。一个Inode指针要么不对应任何文件的Data block,要么对应一个文件的一个或者多个Data block。在Ext3文件系统中一个Inode指针的长度为4字节,按照一个字节8个bit计算Ext3文件系统中的Inode指针支持32位Data block寻址(2 ^ 32个地址);到了Ext4文件系统,虽然它不再使用Inode指针,但同样有地址索引的概念,并且长度扩展到了6字节,那么按照一个字节8个bit计算,Ext4文件系统中的索引支持48位Data block寻址(2 ^ 48个地址)。所以如果按照单个Data block记录4KB数据大小来计算,Ext3文件系统支持的最大理论总容量就是:2 ^ 32 * 4KB / 1024 / 1024 / 1024 = 16TB,而Ext4文件系统支持的最大理论总容量就是 2 ^ 48 * 4KB / 1024 / 1024 / 1024 = 1,048,576TB = 1024 * 1024TB。
Ext2/Ext3文件系统的Inode信息存放在block group的Inode Table区域,这个区域的默认大小为512个block,那么再根据文件系统中单个Inode的大小就可以得到每个block group所管理的Inode总数。例如当单位Inode的大小为256字节,得出每个block group所管理的Inode总数为 512 * 4096字节 / 256字节 = 8192(Ext4文件系统);当Inode的大小为128字节,得出每个block group所管理的Inode总数为 512 * 4096字节 / 128字节 = 16384 (Ext3文件系统)
Ext2/Ext3文件系统中每个Inode结构中至少包括以下的信息:文件的权限定义、创建者、创建时间、最后一次修改事件、删除时间、文件唯一编号以及12个直接关联指针、1个间接关联指针、1个两级间接指针、1个三级间接指针、1个四级间接指针等。文件的权限定义等信息无需进行太多的说明,通过ls命令都可以查看到这些信息,这里重点讲解一下Inode中的直接关联指针和间接关联指针。
所谓直接关联是指Inode中4字节的信息直接指向一个Data block的位置,并可以从Data block中读取文件数据。间接关联是指Inode中4个字节的信息指向一个Data block,不过这个Data block中存储的信息并不是真实的文件数据而是将这个Data block控制的4KB空间模拟成1024个新的Inode索引(Inode大小为4字节,所以4KB / 4Byte = 1024),并分别指向若干新的Data blocks。
当从一个Inode开始,需要跳过一级这种模拟Inode的Data block才能到达真正用于记录数据的Data block,这种关联称为间接关联,原始的Inode指针称为间接关联指针;当从一个Inode开始,需要跳过两级这种模拟Inode的Data block才能到达真正用于记录数据的Data block,这种关联称为两级间接关联,原始的Inode指针称为两级间接关联指针。。。以此类推Ext2、Ext3文件系统中最多支持四级间接关联指针。这样我们就可以计算出一个Inode支持的最大Data block数量,由于一个Inode最多对应一个文件,所以这个数量就可以推导出Ext2/Ext3系统中支持的单个文件的最大容量:
以上推导过程是在Ext3文件系统下,Inode寻址位宽为32位并且在进行文件系统格式化时设置的block大小为4KB的情况下进行的。如果在文件系统格式化时设置的block大小为8KB则系统支持的单个文件最大容量就变成了8TB。
==============================================================
(接下文)