我们无时无刻不在使用文件系统,进行开发时在使用文件系统,浏览网页时在使用文件系统,玩手机时也在使用文件系统。
对于非专业人士来说,可能根本不知道文件系统为何物。因为,通常来说,我们在使用文件系统时一般不会感知到文件系统的存在。即使是程序开发人员,很多人对文件系统也是一知半解。
虽然文件系统经常不被感知,但是文件系统是非常重要的。在 linux 中,文件系统是其内核的四大子系统之一;微软的 DOS(Disk Operating System,磁盘管理系统),核心就是一个管理磁盘的文件系统,由此可见文件系统的重要性。
01
常见文件系统及分类
其实文件系统发展到现在,其种类也丰富多样。比如,基于磁盘的普通本地文件系统除了 Ext4,还包括 XFS、ZFS 和 Btrfs 等。其中 Btrfs 和 ZFS 不仅可以管理一块磁盘,还可以实现多块磁盘的管理。不仅如此,这两个文件系统实现了数据的冗余管理,这样可以避免磁盘故障导致的数据丢失。除了对磁盘数据管理的文件系统,还有一些网络文件系统。也就是说,这些文件系统看似在本地,但其实数据是在远程的专门设备上。客户端通过一些网络协议实现数据的访问,如 NFS 和 GlusterFS 等文件系统。经过几十年的发展,文件系统的种类非常多,我们没有办法逐一进行介绍。下面就对主要的文件系统进行介绍。
本地文件系统
本地文件系统是对磁盘空间进行管理的文件系统,也是最常见的文件系统形态。从呈现形态上来看,本地文件系统就是一个树形的目录结构。本地文件系统本质上就是实现对磁盘空间的管理,实现磁盘线性空间与目录层级结构的转换,如下图所示。
从普通用户的角度来说,本地文件系统主要方便了对磁盘空间的使用,降低了使用难度,提高了利用效率。常见的本地文件系统有 Ext4、Btrfs、XFS 和 ZFS 等。
伪文件系统
伪文件系统是 Linux 中的概念,它是对传统文件系统的延伸。伪文件系统并不会持久化数据,而是内存中的文件系统。它是以文件系统的形态实现用户与内核数据交互的接口。常见的伪文件系统有 proc、sysfs 和 configfs 等。
在 Linux 中,伪文件系统主要实现内核与用户态的交互。比如,我们经常使用的 IOStat 工具,其本质上是通过访问/proc/diskstats 文件获取信息的,如下图所示。而该文件正是伪文件系统中的一个文件,但其内容其实是内核中对磁盘访问的统计,它是内核某些数据结构的实例。
网络文件系统
网络文件系统是基于 TCP/IP 协议(整个协议可能会跨层)的文件系统,允许一台计算机访问另一台计算机的文件系统,就如访问本地文件系统一样。网络文件系统通常分为客户端和服务端,其中客户端类似本地文件系统,而服务端则是对数据进行管理的系统。网络文件系统的使用与本地文件系统的使用没有任何差别,只需要执行 mount 命令挂载即可。网络文件系统也有很多种类,如 NFS 和 SMB 等。
在用户层面,完成挂载后的网络文件系统与本地文件系统完全一样,看不出任何差异,对用户是透明的。网络文件系统就好像将远程的文件系统映射到了本地。如下图所示,左侧是客户端,右侧是文件系统服务端。
当在客户端对服务端导出的文件系统进行挂载后,服务端的目录树就成为客户端目录树的一颗子树。这个子目录对普通用户来说是透明的,不会感知到这是一个远程目录,但实际上读/写请求需要通过网络转发到服务端进行处理。
集群文件系统
集群文件系统本质上也是一种本地文件系统,只不过它通常构建在基于网络的SAN 设备上,且在多个节点中共享 SAN 磁盘。集群文件系统最大的特点是可以实现客户端节点对磁盘介质的共同访问,且视图具有一致性,如下图所示。这种视图的一致性是指,如果在节点 0 创建一个文件,那么在节点 1 和节点 2都可以马上看到。这个特性其实跟网络文件系统类似,网络文件系统也是可以在某个客户端看到其他客户端对文件系统的修改的。但是两者是有差异的,集群文件系统本质上还是构建在客户端的,而网络文件系统则是构建在服务端的。
同时,对于集群文件系统来说,其最大的特点是多个节点可以同时为应用层提供文件系统服务,特别适合用于业务多活的场景,通过集群文件系统提供高可用集群机制,避免因为宕机造成服务失效。
分布式文件系统
从本质上来说,分布式文件系统其实也是一种网络文件系统。在《计算机科学技术名词》中给出的定义为“一种文件系统,所管理的数据资源存储在分布式网络节点上,提供统一的文件访问接口”,可以看出,分布式文件系统与网络文件系统的差异在于服务端包含多个节点,也就是服务端是可以横向扩展的。从使用角度来说,分布式文件系统的使用与网络文件系统的使用没有太大的差异,也是通过执行 mount 命令挂载,客户端的数据通过网络传输到服务端进行处理。
我们发现常规的网络文件系统最大的缺点是服务端无法实现横向扩展。这个缺点对大型互联网应用来说几乎是不可容忍的。本文将介绍一下在互联网领域应用非常广泛的分布式文件系统。分布式文件系统最大的特点是服务端通过计算机集群实现,可以实现横向扩展,存储端的存储容量和性能可以通过横向扩展的方式实现近似线性的提升。
02
什么是分布式文件系统
分布式文件系统(Distributed File System,简称 DFS)是网络文件系统的延伸,其关键点在于存储端可以灵活地横向扩展。也就是可以通过增加设备(主要是服务器)数量的方法来扩充存储系统的容量和性能。同时,分布式文件系统还要对客户端提供统一的视图。也就是说,虽然分布式文件系统服务由多个节点构成,但客户端并不感知。在客户端来看就好像只有一个节点提供服务,而且是一个统一的分布式文件系统。
在分布式文件系统中,最出名的就是谷歌的 GFS。除此之外,还有很多开源的分布式文件系统,比较有名且应用比较广泛的分布式文件系统有 HDFS、GlusterFS、CephFS、MooseFS 和 FastDFS 等。
分布式文件系统的具体实现有很多方法,不同的文件系统通常用来解决不同的问题,在架构上也有差异。虽然分布式文件系统有很多差异,但是有很多共性的技术点。
在有些情况下,NFS 等网络文件系统也被称为分布式文件系统。但是在本文中,分布式文件系统是指服务端可以横向扩展的文件系统。也就是说,分布式文件系统最大的特点是可以通过增加节点的方式增加文件系统的容量,提升性能。
当然,分布式文件系统与网络文件系统也有很多相同的地方。比如,分布式文件系统也分为客户端的文件系统和服务端的服务程序。同时,由于客户端与服务端分离,分布式文件系统也要实现网络文件系统中类似 RPC 的协议。
另外,分布式文件系统由于其数据被存储在多个节点上,因此还有其他特点。包括但不限于以下几点。
由于分布式文件系统需要客户端与多个服务端交互,并且需要实现服务端的容错,通常来说,分布式文件系统都会实现私有协议,而不是使用 NFS 等通用协议。
03
常见分布式文件系统
分布式文件系统的具体实现方法有很多,其实早在互联网兴盛之前就有一些分布式文件系统,如 Lustre 等。早期分布式文件系统更多应用在超算领域。
随着互联网技术的发展,特别是谷歌的 GFS 论文的发表,分布式文件系统又得到进一步的发展。目前,很多分布式文件系统是参考谷歌发布的关于 GFS 的论文实现的。比如,大数据领域中的 HDFS 及一些开源的分布式文件系统 FastDFS 和CephFS 等。
在开源分布式文件系统方面,比较知名的项目有大数据领域的 HDFS 和通用的CephFS 和 GlusterFS 等。这几个开源项目在实际生产中使用得相对比较多一些。接下来将对常见的分布式文件系统进行简要的介绍。
GFS
GFS 是谷歌的一个分布式文件系统,该分布式文件系统因论文 The google File System广为世人所知。GFS 并没有实现标准的文件接口,也就是其实现的接口并不与 POSIX 兼容。但包含创建、删除、打开、关闭和读/写等基本接口。
GFS 集群节点包括两个基本角色:一个是 master,该角色的节点负责文件系统级元数据管理;另一个是 chunkserver,该角色的节点通常有很多个,用于存储实际的数据。GFS 对于文件的管理是在 master 完成的,而数据的实际读/写则可以直接与 chunkserver 交互,避免 master 成为性能瓶颈。
GFS 在实现时做了很多假设,如硬件为普通商用服务器、文件大小在数百兆甚至更大及负载以顺序大块读者为主等。其中,对于文件大小的假设尤为重要。基于该假设,GFS 默认将文件切割为 64MB 大小的逻辑块(chunk),每个 chunk 生成一个 64 位的句柄,由 master 进行管理。
这里需要重点强调的是,每个 chunk 生命周期和定位是由 master 管理的,但是chunk 的数据则是存储在 chunkserver 的。正是这种架构,当客户端获得 chunk 的位置和访问权限后可以直接与 chunkserver 交互,而不需要 master 参与,进而避免了master 成为瓶颈。
下图所示为 GFS 架构示意图。
除了 GFS,还有很多类似架构的分布式文件系统。比如,在大数据领域中的HDFS,它是专用于 Hadoop 大数据存储的分布式文件系统。其架构与 GFS 的架构类似,包含一个用于管理元数据的节点和多个存储数据的节点,分别为 namenode和datanode。
HDFS 主要用来进行大文件的处理,它将文件按照固定大小切割,然后存储到数据节点。同时为了保证数据的可靠性,这些数据被放到多个不同的数据节点。文件被切割的大小和同时放置数据节点的数量(副本数)是可配置的。
虽然 HDFS 是针对大文件设计的,但是也可以处理小文件。只不过对于小于切割单元的文件不进行切割。另外,HDFS 对小文件也做了一些优化,如 HAR 和SequenceFile 等方案,但 HDFS 终究不是特意为小文件设计的,因此在性能方面还有些欠缺。
除此之外,还有很多模仿 GFS 的开源分布式文件系统,如 FastDFS、MooseFS和 BFS 等。但大多数开源项目只实现了文件系统最基本的语义,严格来说不能称为分布式文件系统,更像是对象存储。
CephFS
有必要单独介绍一下 CephFS 的原因是 CephFS 不仅实现了文件系统的所有语义,而且实现了元数据服务的多活横向扩展。
CephFS 的架构与 GFS 的架构没有太大差别,其突出的特点是在架构方面将GFS 的单活 master 节点扩展为多活节点。不仅可以元数据多活,而且可以根据元数据节点的负载情况实现负载的动态均衡。这样,CephFS 不仅可以通过增加节点来实现元数据的横向扩展,还可以调整节点负载,最大限度地使用各个节点的 CPU资源。
同时,CephFS 实现了对 POSIX 语言的兼容,在客户端完成了内核态和用户态两个文件系统实现。当用户挂载 CephFS 后,使用该文件系统可以与使用本地文件系统一样方便。
GlusterFS
GlusterFS 是一个非常有历史的分布式文件系统,其最大的特点是没有中心节点。也就是 GlusterFS 并没有一个专门的元数据节点来管理整个文件系统的元数据。
GlusterFS 抽象出卷(Volume)的概念,需要注意的是,这里的卷与 Linux LVM中的卷并非同一个概念。这里的卷是对文件系统的一个抽象,表示一个文件系统实例。当我们在集群端创建一个卷时,其实是创建了一个文件系统实例。
GlusterFS 有多种不同类型的卷,如副本卷、条带卷和分布式卷等。正是通过这些卷特性的组合,GlusterFS 实现了数据可靠性和横向扩展的能力。