文件系统简介
1、文件系统相关概念
计算机的文件系统是一种存储和组织计算机数据的方法,它使得对其访问和查找变得容易,文件系统使用文件和树形目录的抽象逻辑概念代替了硬盘和光盘等物理设备使用数据块的概念,用户使用文件系统来保存数据不必关心数据实际保存在硬盘(或者光盘)的地址为多少的数据块上,只需要记住这个文件的所属目录和文件名。在写入新数据之前,用户不必关心硬盘上的那个块地址没有被使用,硬盘上的存储空间管理(分配和释放)功能由文件系统自动完成,用户只需要记住数据被写入到了哪个文件中。
文件系统通常使用硬盘和光盘这样的存储设备,并维护文件在设备中的物理位置。但是,实际上文件系统也可能仅仅是一种访问数据的界面而已,实际的数据是通过网络协议(如NFS、SMB、9P等)提供的或者内存上,甚至可能根本没有对应的文件(如proc文件系统)。
严格地说,文件系统是一套实现了数据的存储、分级组织、访问和获取等操作的抽象数据类型(Abstract data type)。
文件系统是一种用于向用户提供底层数据访问的机制。它将设备中的空间划分为特定大小的块(或者称为簇),一般每块512字节。数据存储在这些块中,大小被修正为占用整数个块。由文件系统软件来负责将这些块组织为文件和目录,并记录哪些块被分配给了哪个文件,以及哪些块没有被使用。
不过,文件系统并不一定只在特定存储设备上出现。它是数据的组织者和提供者,至于它的底层,可以是磁盘,也可以是其它动态生成数据的设备(比如网络设备)。
空闲空间示例:每簇4,096字节的NTFS文件系统,每个文件5字节,共100,000个文件,逻辑字节总共500,000字节,但由于一个文件需独占整数倍个簇(最后一簇无论是否占满,仍会独占一整个簇),实际占用磁盘空间409,600,000字节(每个文件5字节独占一个簇)
2、文件系统分类
一般而言,磁盘需要格式化成相应的格式才能存放数据,当然也有特例,如 Oracle 数据库则支持使用裸盘,即不需要对磁盘进行格式化操作。我们了解即可。
常见的文件系统可分为 3 类
本地本件系统
- Windows平台:FAT、NTFS、ReFS
- Linux平台:Ext系列、XFS、ZFS、Btrfs
- macOS平台:HFS、HFS+、APFS
网络文件系统
- NFS
- CIFS(samba)
分布式文件系统
- GFS
- HDFS
- Lustre
- Ceph
- GridFS
- mogileFS
- TFS
- FastDFS
其它
- 光盘:CDFS、UDF
- 虚拟机:VMFS、QCOW2、RAW
- 伪文件系统:ramfs、tmpfs、sys、proc 等
2.1、本地文件系统
本地文件系统是指由操作系统直接管理的,由相关的文件系统管理工具格式化后生成。如将一个磁盘分区格式化为 ext4 的命令则为:
mkfs -t ext4 /dev/sdb1
下面主要以 Linux 常用的文件系统格式来讲解。
- ext
第一代扩展文件系统,于1992年4月发表,是为linux核心所做的第一个文件系统。采用Unix文件系统(UFS)的元数据结构,以克服MINIX文件系统性能不佳的问题 - ext2
第二代扩展文件系统,它开始由Rémy Card设计,用以代替ext,于1993年1月加入linux核心支持之中。ext2 的经典实现为LINUX内核中的ext2fs文件系统驱动,最大可支持2TB的文件系统,至linux核心2.6版时,扩展到可支持32TB - ext3
第三代扩展文件系统,在ext2的基础上添加日志功能,能有效的防止断电后数据丢失的问题。是Linux系统最广泛使用的文件系统之一 - ext4
第四代扩展文件系统,是ext3文件系统的后继版本。主要增强了性能和更丰富的功能和支持更大的文件和磁盘容量,支持1EB容量,文件最大支持16TB。虽然 ext4 依然是目前主流 Linux 发行版的默认选择,但它是毕竟是老家伙了,很多企业级的特性它不支持。事实上,现代发行版都逐渐使用 xfs、btrfs 等文件系统取代 ext4. - xfs
XFS 文件系统是扩展文件系统的一个扩展。XFS 是 64 位高性能日志文件系统。对 XFS 的支持大概在 2002 年合并到了 Linux 内核,到了 2009 年,红帽企业版 Linux 5.4 也支持了 XFS 文件系统。对于 64 位文件系统,XFS 支持最大文件系统大小为 8 exbibytes。XFS 文件系统有一些缺陷,例如它不能压缩,删除大量文件时性能低下。目前 RHEL 7 文件系统默认使用 XFS。 - btrfs
btrfs 出现的原因是它的开发者起初希望扩展文件系统的功能使得它包括快照、池化(pooling)、校验以及其它一些功能,其参考对象是 zfs。虽然和 ext4 无关,它也希望能保留 ext4 中能使消费者和企业受益的功能,并整合额外的能使每个人,尤其是企业受益的功能。对于使用大型软件以及大规模数据库的企业,让多种不同的硬盘看起来一致的文件系统能使他们受益并且使数据整合变得更加简单。删除重复数据能降低数据实际使用的空间,当需要镜像一个单一而巨大的文件系统时使用 btrfs 也能使数据镜像变得简单。
用户当然可以继续选择创建多个分区从而无需镜像任何东西。考虑到这种情况,btrfs 能横跨多种硬盘,和 ext4 相比,它能支持 16 倍以上的磁盘空间。btrfs 文件系统一个分区最大是 16 exbibytes,最大的文件大小也是 16 exbibytes。 - zfs
ZFS 由 Matthew Ahrens 和 Jeff Bonwick 于 2001 年创建。ZFS 旨在成为 Sun Microsystems 的 OpenSolaris 的下一代文件系统。 2008 年,ZFS 被移植到 FreeBSD。同年,一个项目开始将 ZFS 移植到 Linux。但是,由于 ZFS 根据与 GNU 通用公共许可证不兼容的通用开发和分发许可证进行许可,因此它不能包含在 Linux 内核中。为了解决这个问题,大多数 Linux 发行版提供了安装 ZFS 的方法。
ZFS 的高级特性在文末有详细的说明。
2.2、网络文件系统
常见的网络文件系统有两种,它们分别是 nfs 、cifs。
- nfs(Network File System)
Linux 中很常用,常用于做小量文件的文件共享服务 - cifs(Common Internet File System)
Windows 系统的文件共享协议
Linux 中的 Samba 也是基于 cifs
这里就不展开讲解了,有兴趣的同学自行搜索相关资料了解。
2.3、分布式文件系统
谷歌公司在 2003 年相继发布了 GFS、MapReduce、BigTable 三篇论文,一经发表,在 IT 界引起了一石千层浪的效果。Hadoop、HDFS 即是开源界根据谷歌论文的开源实现,也为后来推出的分布式文件系统和大数据处理产品奠定了基础。
- GFS(Google File System)
Google公司为了满足本公司需求而开发的基于Linux的专有分布式文件系统。。尽管Google公布了该系统的一些技术细节,但Google并没有将该系统的软件部分作为开源软件发布。
下面分布式文件系统都是类 GFS的产品。 - HDFS(Hadoop Distributed File System)
是 Hadoop 项目的一个子项目 - Ceph
Ceph是一个统一的分布式存储系统,设计初衷是提供较好的性能、可靠性和可扩展性。
Ceph项目最早起源于Sage就读博士期间的工作(最早的成果于2004年发表),并随后贡献给开源社区。在经过了数年的发展之后,目前已得到众多云计算厂商的支持并被广泛应用。RedHat及OpenStack都可与Ceph整合以支持虚拟机镜像的后端存储。 - Lustre
Lustre是HP,Intel,Cluster File System公司联合美国能源部开发的Linux集群并行文件系统。是第一个基于对象存储设备的,开源的并行文件系统。 - MogileFS
MogileFS是Perl语言研发的一款分布式文件系统,适合存放海量小文件。 - mooseFS
MooseFS是一个具备冗余容错功能的分布式网络文件系统,它将数据分别存放在多个物理服务器或单独磁盘或分区上,确保一份数据有多个备份副本。对于访问的客户端或者用户来说,整个分布式网络文件系统集群看起来就像一个资源一样。 - FastDFS
是一款类似Google FS的开源分布式文件系统,是纯C语言开发的。
FastDFS是一个开源的轻量级分布式文件系统,它对文件进行管理,功能包括:文件存储、文件同步、文件访问(文件上传、文件下载)等,解决了大容量存储和负载均衡的问题。特别适合以文件为载体的在线服务,如相册网站、视频网站等等。 - GridFS
GridFS是MongoDB的一个内置功能,它提供一组文件操作的API以利用MongoDB存储文 件,GridFS的基本原理是将文件保存在两个Collection中,一个保存文件索引,一个保存文件内容,文件内容按一定大小分成若干块,每一块存在 一个Document中,这种方法不仅提供了文件存储,还提供了对文件相关的一些附加属性(比如MD5值,文件名等等)的存储。文件在GridFS中会按 4MB为单位进行分块存储。
3、延伸阅读
在 Oracle 公司收购 Sun 公司之后不久,OpenSolaris 就闭源了,这使得 ZFS 的之后的开发也变成闭源的了。许多 ZFS 开发者对这件事情非常不满。 三分之二的 ZFS 核心开发者 ,包括 Ahrens 和 Bonwick,因为这个决定而离开了 Oracle 公司。他们加入了其它公司,并于 2013 年 9 月创立了 OpenZFS 这一项目。该项目引领着 ZFS 的开源开发。
让我们回到上面提到的许可证问题上。既然 OpenZFS 项目已经和 Oracle 公司分离开了,有人可能好奇他们为什么不使用和 GPL 兼容的许可证,这样就可以把它加入到 Linux 内核中了。根据 OpenZFS 官网 的介绍,更改许可证需要联系所有为当前 OpenZFS 实现贡献过代码的人(包括初始的公共 ZFS 代码以及 OpenSolaris 代码),并得到他们的许可才行。这几乎是不可能的(因为一些贡献者可能已经去世了或者很难找到),因此他们决定保留原来的许可证。
3.1、ZFS 的高级特性 - 存储池
ZFS 使用存储池的概念来管理物理存储。以前,文件系统是在单个物理设备的基础上构造的。为了利用多个设备并提供数据冗余,ZFS 引入了卷管理器的概念,以便于在不修改文件系统的情况下即可利用多个设备。ZFS 将存储设备聚集到存储池中,而不是强制要求创建虚拟卷。文件系统不再仅限于单个存储设备,从而可与存储池中的所有文件系统共享磁盘空间。与传统的类 Unix 文件系统不同,在创建 ZFS 文件系统时无需指定分区的大小,而是一次将特定数量的磁盘(称为 vdev)提供给 ZFS 池,并根据需要从池中创建文件系统,ZFS 会根据需要自动的使用存储设备上的可用空间。添加新存储器后,无需执行其他操作,存储池中的所有文件系统可立即使用所增加的磁盘空间。
3.2、ZFS 的高级特性 - RAID-Z
ZFS 不需要任何额外软件或硬件就可以处理 RAID(磁盘阵列)。毫不奇怪,因为 ZFS 有自己的 RAID 实现:RAID-Z 。RAID-Z 是 RAID-5 的一个变种,不过它克服了 RAID-5 的写漏洞:意外重启之后,数据和校验信息会变得不同步(LCTT 译注:RAID-5 的条带在正写入数据时,如果这时候电源中断,那么奇偶校验数据将跟该部分数据不同步,因此前边的写无效;RAID-Z 用了 “可变宽的 RAID 条带” 技术,因此所有的写都是全条带写入)。为了使用 基本级别的 RAID-Z (RAID-Z1),你需要至少三块磁盘,其中两块用来存储数据,另外一块用来存储 奇偶校验信息 。而 RAID-Z2 需要至少两块磁盘存储数据以及两块磁盘存储校验信息。RAID-Z3 需要至少两块磁盘存储数据以及三块磁盘存储校验信息。另外,只能向 RAID-Z 池中加入偶数倍的磁盘,而不能是奇数倍的。
3,3、ZFS 的高级特性 - 校验和与自我修复数据
ZFS 文件系统上的所有数据和元数据,均按用户指定的校验和算法进行验证。传统的文件系统,某些故障可能导致数据不正确但却没有校验和错误,比如,会向错误位置写入完整的数据块。ZFS 校验和的存储方式可确保检测到这些故障并可以正常地从其中进行恢复。当 ZFS 写入数据时,它会为其写入的每个磁盘块创建一个校验和。当 ZFS 读取数据时,它会验证它读取的每个磁盘块的校验和。此外,ZFS 还提供自我修复数据。如果 ZFS 在镜像池或使用 RAIDZ 的池上标识磁盘块校验和错误,ZFS 将使用正确的数据修复损坏的数据。ZFS 支持存储池具有各种级别的数据冗余性。检测到坏的数据块时,ZFS 会从另一个冗余副本中提取正确的数据,而且会用正确的数据替换错误的数据。所有校验和验证与数据恢复都是在文件系统层执行的,并且对应用程序是透明的。由于某些磁盘块很少被读取,因此应该安排定期擦除,以便 ZFS 可以读取所有数据块以验证其校验和并纠正任何损坏的块。
3.4、ZFS 的高级特性 - 写时复制
写时拷贝 (Copy-on-write)是另一个有趣并且很酷的特性。在大多数文件系统上,当数据被重写时,它将永久丢失。而在 ZFS 中,新数据会写到不同的块。写完成之后,更新文件系统元数据信息,使之指向新的数据块(LCTT 译注:更新之后,原数据块成为磁盘上的垃圾,需要有对应的垃圾回收机制)。这确保了如果在写新数据的时候系统崩溃(或者发生其它事,比如突然断电),那么原数据将会保存下来。这也意味着,在系统发生崩溃之后,不需要运行 fsck 来检查和修复文件系统。
3.5、ZFS 的高级特性 - 快照
ZFS通过使用 Copy-on-Write 方式提供 Snapshot 功能。ZFS 下的 Snapshot 为系统提供了更安全有效的数据保护方式。在创建一个新的 Snapshot 快照时,系统仅仅简单的复制一个根节点,新的 Snapshot 节点与原始的根节点指向完全想通的数据块,一段时间后,如果数据块发生了变化,比如删除一个文件,那么在文件系统中这个文件已经不再存在,但在磁盘上并没有真正删除这个文件,Snapshot 快照中仍然保存着指向这个文件所在位置的数据块,也就是说,通过 Snapshot 仍然可以找回这个文件。如果在文件系统中修改一个文件,系统在修改之前会复制这个文件所在的数据块,然后修改根节点的相关数据,最后才对这个文件进行修改,这样,使用 Snapshot 仍然可以找回被修改的部分。
ZFS 文件系统中的 Snapshot 是文件系统的只读副本,Snapshot 快照几乎可以即时创建,而且最初不占用池中的其他磁盘空间。但是,当活动数据集中的数据发生更改时,快照通过继续引用旧数据占用磁盘空间,从而阻止释放磁盘空间。
ZFS文件系统中的Snapshot具有以下特征:
- 可在系统重新引导后保存下来。
- 理论最大快照数是2的64次方。
- 快照不使用单独的后备存储。快照直接占用存储池(创建这些快照的文件系统或卷所在的存储池)中的磁盘空间。
3.6、ZFS 的高级特性 - 支持实时数据压缩
在数据块写入磁盘时会进行压缩。当访问一个被压缩的数据块时,它会被自动解压。因为压缩发生在数据块层面,而不是文件层面,因此所有应用程序都可以透明的访问被压缩的数据。
以下是FreeNAS支持的压缩算法:
- lz4:推荐的压缩方法,因为它允许压缩数据集以接近实时的速度运行。这是自FreeNAS 9.2.1开始,系统默认选用的压缩算法,它对系统性能影响小,向数据集中存取数据的速度几乎与不采用压缩时一样。
- gzip:此压缩算法分为 9 个级别,数字越大,压缩效果越好,速度也最慢。fastest (level 1) 压缩率最低,速度最快。maximum (level 9) 压缩率最高,速度最慢。gzip 压缩算法的默认值为level 6,即压缩率适中,速度也适中。但由于其性能影响而不推荐使用。
- zle:快速且简单的压缩方式,采用消除runs of zeroes的方式来压缩空间。
- lzjb:压缩能力很好,但仍不推荐使用,因为lz4提供更好的性能。
3.7、ZFS 的高级特性 - 重复数据删除技术
Deduplication(重复数据删除)是一种可以大大减少数据的数量的存储技术。ZFS 通过比较存储在数据集中重复的数据,对相同数据只保留一个副本,从而消除冗余数据,以此来提高存储系统的效率,有效节约成本、减少传输过程中的占用的网络带宽,是不是听起来很美好?请注意阅读完本文再做决定。
按照重复数据删除的粒度可以分为 file-level 文件级,block-level 块级或者 byte-level 字节级。
- 文件级的去重对文件作为整体来计算hash签名,如果处理的是自然的文件,则此方法需要的消耗最小,但是缺点是对文件的任何修改都需要重新计算文件的hash签名,即对文件的任何修改,将使得此文件之前节约的空间消失,因为两个文件将不再相同。此种级别的去重比较适合类似JPEG,MPEG等类型的文件,但是对于像虚拟机镜像(大文件)文件将无效,因为即使他们只是很小的一部分不同,但是在文件级别,他们是不同的文件。
- 块级别的去重(相同大小的块),相比文件级的去重,需要更多的计算消耗,但是它能够很好地对像虚拟机镜像类似的大文件去重。大部分的虚拟机镜像文件是重复数据,例如镜像文件中的操作系统部分。使用块级的去重将使得只有镜像特别的数据才占用额外的空间,相同的数据将共享。
- 字节级别的去重,将需要更多的计算消耗来决定重复数据的开始和结束区域,字节级别的去重对mail服务器来说是理想的组合,比如一个邮件的附件可能因为大量转发而出现很多次,但是使用块级别去重时他们并不能被优化。此类型的去重一般用来一些应用程序的去重中,例如exchange server,因为应用程序知道他管理的数据,可以在内部去重。
ZFS 采用 Deduplication 能节约的存储空间取决于存入数据集中重复数据的总量。但是,这种技术非常耗费内存,按照官方的建议,通常 1TB 存储空间需要额外提供 5GB 的内存。当启用 Deduplication 时,向数据集写入的数据越多,所需的内存就越多。如果内存过小,容量不足以保存 DDT(重复数据删除表),系统会将 DDT 存储在磁盘上,这将会导致系统性能一落千丈,直至系统崩溃,这就是那个传说中像月球表面一样的陨石坑。此时唯一的解决方案是添加更多的内存或重新创建池。所以,按照官方的说法,除非有大量内存或者存储的数据中有大量的重复数据,否则,请保证将”ZFS Deduplication”设置为“off”。