大数据存储技术
上QQ阅读APP看书,第一时间看更新

| 2.1 文件系统的结构与扩展 |

本章的讨论将从文件系统的名字空间和数据读写开始。这部分针对的是通用的文件系统[1-2],因为分布式文件系统需要提供与文件系统一样的接口与访问方式,不同的是规模上的区别。从文件系统开始讨论便于理解分布式文件系统与本地文件系统的区别,从而进一步理解在分布式环境下需要完成的工作。

2.1.1 文件系统的名字空间与数据读写

(1)磁盘文件系统的功能与实现层次

为了更好地理解如何实现一个分布式文件系统,有必要先对文件系统对外提供的功能进行一番梳理。文件系统在整个系统软件当中处于一个非常重要的地位,文件系统虽然是操作系统中的一个功能模块,但是操作系统的很多功能十分依赖文件系统。一个最为直接的原因就是所有数据需要长期保存在磁盘上,因为磁盘是一个永久的存储。对于内存来说,因为不是永久的存储设备,一旦掉电,内存上的数据就会丢失,因此需要长期保存的数据必须被保存在磁盘中(当然,也有其他的永久存储介质,如新型的固态硬盘(Solid State Disk,SSD)介质)。想象一个系统的启动过程,启动过程在系统加电时必须要有文件系统的支持,因为只有在文件系统的帮助下,操作系统才能把自身从磁盘装载到内存中,之后才可以进入正常执行流程[3-4]。显而易见,在这个过程中文件系统起到了重要的作用。另外,在正常的操作系统工作过程中,也需要文件系统的支持,因为大量的可执行程序以及操作系统的一些必要的系统模块的维护需要在文件系统当中进行。

实际上理解文件系统的功能与实现,还是相对比较容易的。在理解文件系统功能上,需要从两个方面着手,一个是文件系统对上层提供的功能,另一个是文件系统所依赖的基础。从前一个应用方面来看,文件系统需要对上层提供底层磁盘的抽象。对于抽象这个层次来说,没有必要局限于底层的磁盘驱动所能够提供的功能,而是尽量要从文件系统的使用者的角度去考虑问题。文件系统的使用者一般使用目录树的结构。从后一个实现基础的方面来看,磁盘所提供的接口是磁盘块的接口,而磁盘块的接口可以被看作一个磁盘数据块的数组。一般来说,一个磁盘块的大小一般为512 B,每次读写时都是对512 B进行读写。所有的磁盘块可以被看作一个N×512 B(其中N表示磁盘块数量)的大数组。对这种数据块的数组的方式进行读写时,对于驱动程序来说,处理起来会比较方便,但是对于上层应用以及用户程序来说,数据块的接口还是过于底层。应用程序往往会有自己的语义。这种过于底层的接口对于应用程序来说并不是很方便,对于用户来说也比较难以理解。因为从底层的磁盘语义到上层的应用程序语义,二者的差别还是非常大的。这样,构建文件系统的目的就非常清楚了,就是为上层的应用程序或用户提供比较好的语义接口,并且文件系统通过自己的工作将其翻译成底层的数据块的接口,从而将数据保存到磁盘中,或从磁盘中读取数据。

图2-1描述了磁盘、文件系统、操作系统以及应用程序在系统中的层次结构。从这个层次结构中可以明显看到磁盘的读写语义接口与上层文件系统的语义接口的不同。下面对上层的文件系统的语义接口的构成以及对文件系统实现的影响进行分析。

(2)文件系统的名字空间

对用户提供读写的接口时会涉及名字空间的概念。名字空间就是文件系统的文件与目录的集合。在一般的文件系统中,文件和目录都被组织成目录树的形式,一个目录包含了多个文件以及相应的子目录。名字空间对于用户来说是非常容易理解的,这与传统的使用文件夹进行文件整理的方式是类似的。一个完整的目录树构成了一个名字空间。在一个操作系统的内部,不见得只有一个名字空间,例如在Windows操作系统中,每一个磁盘都可以被组织成一个文件系统的名字空间。在引用不同的名字空间中的文件时,必须附带上对应的磁盘的名字。但是,在类似UNIX的操作系统中,所有的文件系统会被组织到同一个名字空间中,从同一个根目录“/”开始组织各个子目录以及存放对应的文件。

图2-1 磁盘、文件系统、操作系统与应用程序在系统中的层次结构

图2-2展示了Windows与UNIX系统中典型的文件系统名字空间。从图2-2可以看到,这两个名字空间本质上都是以目录树的形式展现给用户。不同之处在于,在Windows环境中,一般采用不同磁盘的名字空间不同的方式,而在UNIX环境中,即使是不同的磁盘,其名字空间也被挂载在同一个单一的名字空间中。区分名字空间对于理解文件系统还是相当重要的,这使得用户可以了解当前文件所在的上下文,了解对应的文件所处的位置以及相应的读写特性。

由前文可知,磁盘实际上是数据块的一个数组,而名字空间是目录树的形式,这两者从形式上看是完全不同的。对于磁盘来说,最终还是需要通过目录树的形式,也就是通过名字空间的形式向外提供服务。文件系统在其中起到的作用是将名字空间中以字符串形式表达的文件名对应到磁盘中的数据块。这样,用户就可以通过文件系统的读写接口读写磁盘上的数据。

图2-2 Windows与UNIX系统中典型的文件系统名字空间

(3)名字空间与数据定位

将文件系统的名字空间的读写接口转化为磁盘上的数据块的读写接口,是文件系统最为本质的功能。为了实现这个功能,需要对文件系统的内部数据进行组织。文件系统本质上就是将一个文件名转换成对一系列数据块的描述。在达到这个目的的过程中,文件系统的目录树起到非常重要的作用。在目录树的磁盘数据结构组织中,会为每一个文件以及目录存储相应的元数据。这些元数据会保存对应文件进行读写所需要的相关信息,包括文件大小、文件所占用的具体数据块等。对目录的描述也是一样的,目录的数据块会保存该目录下所有的文件及子目录。因此,目录的数据块也需要在元数据当中进行描述。由此可以看到,有了元数据的帮助,就可以对文件和目录进行读写了,这也是文件系统最基本的功能。为了实现这样的功能,需要文件系统在磁盘上进行目录树的数据结构的组织与设计。现有的文件系统通常使用inode方法,即索引节点的方法,将所有文件元数据保存在inode的节点表中。文件系统被格式化之后,就会在固定的位置存放inode的信息,此时每一个inode对应一个文件或目录。一个文件系统就是将一个文件名对应到一组磁盘块结构的映射,即:文件名→(磁盘块1,磁盘块2,…)。

上面的对应形式虽然有所简化,但是反映了文件系统最为本质的功能。有了这部分的元数据之后,根据这样的信息就可以展开对磁盘的读写工作,也就完成了对文件的读写工作。这部分的工作具体如何在磁盘文件系统中展开,建议读者阅读相应的关于操作系统的书籍,在每一本操作系统的教科书中,都会有专门的一章来讨论磁盘文件系统的组织与实现。本章讨论的重点是分布式文件系统,因此没有必要就磁盘文件系统进行展开。

注意,上述将文件名映射到具体的读写位置的功能,对于分布式文件系统也是一样的。因为分布式文件系统也是一个文件系统,也需要提供与文件系统等同的功能,只是必须要运行在分布式的环境中。在分布式文件系统当中也需要提供域名空间的形式和数据读写的功能。

2.1.2 文件系统的扩展方式

既然分布式文件系统还是一个文件系统,那么与单机文件系统一样,也需要提供名字空间。这样,上层应用程序在看到分布式文件系统时,可以通过调用分布式文件系统提供的功能,对分布式文件系统中的文件进行读写。同单机的磁盘文件系统一样,要理解分布式文件系统同样需要从两个方面着手,一个是前面所说的分布式文件系统的功能(与单机文件系统一样),另一个就是分布式文件的构建基础。单机文件系统的构建基础是单个的磁盘,但是分布式文件系统的构建基础就不只是多个磁盘的问题了。实际上分布式文件系统会运行在几十、数百甚至数千个服务器节点上。在这些节点上可以安装完整的单机的操作系统,如现在广泛使用的Linux操作系统。这种情况下,完全可以让单机文件系统自行管理磁盘上的数据结构的组织,而不需要由分布式文件系统直接控制磁盘数据块的读写。因此,当前的大部分分布式文件系统并不需要直接与磁盘打交道,只需与每一个服务器节点的单机文件系统打交道即可。

从数据定位的角度看,与单机的磁盘文件系统一样,分布式文件系统同样要对名字空间中文件的具体存储位置进行定位。分布式文件系统与单机文件系统最大的区别就是分布式文件系统加入了多台服务器节点。因此,分布式文件系统在定位时不仅需要定位到磁盘上的某一个磁盘块,还需要定位到具体的服务器节点。定位到服务器节点是分布式文件系统额外需要做的工作,可以说,分布式文件系统最本质的功能就是将文件名以及文件中的数据范围定位到具体的服务器节点。分布式文件系统中的关键数据定位可被表示成如下映射方式:(文件名,文件的数据读写范围)→具体的服务器节点。

完成上述定位到具体的服务器节点的工作之后,就可以在单机文件系统的帮助下,对磁盘数据进行读写,进而完成对分布式文件系统中某一个具体文件的数据读写。当前的绝大多数分布式文件的数据读写方式是这种数据读写方式。

可以说,分布式文件系统是对单机文件系统的直接扩展。分布式文件系统的扩展方式有很多种,对应于单机文件系统的实现层次的扩展。由于单机磁盘文件系统的实现有多个不同的层次,因此可以在各个层次进行扩展。单机的文件系统的分层包括底层的磁盘驱动层、文件系统本身的命名空间组织层,以及为上层的应用程序提供读写的用户接口层。在这3个层次上都可以扩展,并有不同的概念来描述在分布式环境下单个磁盘文件不同层次的扩展技术。底层磁盘的扩展方式以及文件系统本身命名空间组织扩展方式是两种典型的对文件系统容量进行分布式扩展的方式。下面分别介绍几种不同的扩展方式以及对构建分布式文件系统的影响。

(1)存储区域网络

对于分布式文件系统来说,其中最为直接的方式就是将底层的磁盘进行扩展,构成一个大规模的磁盘系统。这种方式是企业级存储通用的扩展方式。由于是通过磁盘方式进行的扩展,可以将底层的多块磁盘通过网络组合成一个大的虚拟的磁盘,并且还可向外提供磁盘的接口。这样的扩展方式通常被称为存储区域网络(Storage Area Network,SAN)。

图2-3给出的是存储区域网络的结构。在存储端,磁盘被直接插入内部的高速网络中,前端的服务器可以直接看到磁盘的接口。为了能够访问这些暴露出来的接口,可以让前端应用服务器直接与每一块磁盘进行交互,对每一块磁盘进行独立访问,但是这会导致前端应用服务器的工作变得烦琐。一般来说,存储区域网络通过磁盘控制器的方式,将多个磁盘联合在一起,构造成一个大的虚拟的磁盘。对于前端应用服务器来说,需要处理少数但容量巨大的磁盘。这也被称为网络磁盘的虚拟化。通过SAN的方式进行存储系统的扩展的一个直接的好处是对于前端应用系统来说,其面对的存储设备与原先的单机的存储设备并没有本质的不同。所有的磁盘驱动、操作系统以及应用程序除了面对一个容量巨大的磁盘,其他特征都与原来的硬件环境相同。这种方式对于上层的所有软件(包括操作系统)来说都是透明的,可以直接运行而不需要进行修改。

图2-3 存储区域网络的结构

但是,上述存储区域网络也存在一定的缺陷。在成本方面,存储区域网络一般使用专门的磁盘以及磁盘控制器。专门的磁盘可以被直接插入网线,并被接入网络中。磁盘控制器需要重新设计,并且需要一个总的磁盘控制器帮助完成磁盘虚拟化的工作。这样的设计往往会直接固化在硬件或固件(固定的程序)中,造成建立的系统成本很高。在服务接口的提供方面,由于暴露出来的是磁盘的接口,因此不能像FTP或Samba一样供远程的用户或应用程序直接使用,而是需要将一台服务器作为文件系统的服务器,并在磁盘上建立文件系统才可以向外提供接口。在可扩展性方面,由于存储区域网络的扩展性来自其硬件的连线以及内部网络的规模,不太可能扩展到巨大的规模,因此存储控制器的计算能力相对有限。其服务能力是有限的,非常适合在企业内部作为文件系统或数据库存储使用。然而,在云计算、大数据处理方面,面对超大规模的用户数目,以及需要进行海量数据处理任务时,就往往显得力不从心了。

当然,为了能够更好地利用虚拟磁盘上的存储空间,在建立文件系统时可以不使用现有的针对单机磁盘的文件系统,而是针对多个磁盘构建新的文件系统。这样的文件系统往往被称为SANFS(SAN File System)。因为底层是由多个分布式网络上的磁盘共同组成的大的虚拟磁盘,所以SANFS可以提高文件系统在分布式环境下的性能,例如将元数据以及数据可以尽可能并行地放置在更多的磁盘上,以支持磁盘的并行读写。这种具体的工作方式对于上层应用是透明的,应用程序并不需要知道底层的数据分布情况。对于文件系统来说,则需要通过直接操作这些信息来实现文件系统的功能,满足分布式文件系统的快速访问、数据可靠等特性。这种情况下,SANFS虽然是一个分布式系统,但是可以直接访问物理磁盘,其中的实现难度可想而知。在分布式环境下,往往不需要直接接触物理资源,这反映在分布式存储上就是不需要直接接触具体的物理磁盘的读写。因为分布式系统往往构建在大规模的集群当中,集群中的每一个节点都是完整的计算机,可以安装操作系统。而这个操作系统肯定会包含相应的单机的文件系统,以管理本地磁盘上的数据。分布式系统可以利用本地的一些应用程序与操作系统管理物理资源,在构建时基于抽象的服务构建即可,这会大大降低实现的难度,提高系统的稳定性。

(2)网络附加存储

上述磁盘扩展方式是数据存储的一种典型扩展方式,其通过数据块的接口进行扩展。也可以在文件系统的层次上进行扩展,这样对外就可以直接提供文件的服务,上层应用程序可以透明地使用文件系统所提供的功能。这种方式是一个一体化的解决方案,不需要主机服务器再执行操作系统的工作。这样的扩展方式可以让远程的节点通过网络协议来访问存放在服务器中的数据,因此被称为网络附加存储(Network Attached Storage,NAS)。

图2-4展示了网络附加存储的组织结构。从图2-4可以看到,客户端可以通过标准的网络接口访问服务器上的存储空间。这里的标准网络接口普遍包括两个完整的文件系统语义协议,一个是专门针对类似UNIX系统的网络文件系统(Network File System,NFS)协议,另一个是专门针对Windows系统的Samba协议。当然,随着网络协议的发展,一些面向对象的协议或针对特定应用的特殊的协议相继出现。

图2-4 网络附加存储的结构

上述协议都是远程的节点访问分布式文件系统中的数据时,需要在网络上交互的约定协议。这样的话,与磁盘层次的扩展不同,在文件系统层次上的扩展可以考虑两个方面的内容,一个是服务器与客户端交互的协议方面的设计,另一个是后台服务器方面的设计。

在协议设计方面,现有的协议包括NFS、Samba等标准的文件系统的协议,也包括Swift、JSON等面向对象的协议。在协议优化方面,主要研究如何减少协议本身带来的负担。例如在很长的一段时间内,很多传输协议都是基于XML接口的,但是这样的协议接口负担太重,因此现有的很多协议对此进行了简化,大大降低了协议的开销。

协议的一些特性也直接影响了网络上数据传输的性能。例如,在NFSv4协议中加入了对物理资源的描述的协议。这里需要引入带外(Out-Bound)存储访问和带内(In-Bound)存储访问的模式。这个概念涉及传统的磁盘访问方式。对于传统的磁盘访问来说,驱动程序以及文件系统都知道自己访问的是一个唯一的磁盘(可能是虚拟的)。因此,文件系统的客户端进行访问时,直接将访问的请求发送给文件系统即可。但是,如果涉及多个磁盘或多个节点,就需要查看客户端如何访问多个磁盘了。如果客户端不知道有多个磁盘或多个节点,直接将访问请求发送给一个已知的服务器,并且由这个已知的服务器访问后台的存储,这种方式就是带内的访问。对于客户端来说,带内的访问具有透明性,不需要知道后台服务器的配置情况。相应地,由于不知道数据分布的情况,客户端发送请求和获得请求的时间就比较长,性能会受到一定的影响。但是,如果客户端知道数据分布的情况,在发送请求时就可以自行决定将多个请求发送给哪一些服务器,即可以并行发送请求,充分利用网络带宽,从而缩短数据获得的时间。这种让客户端了解后台节点的分布情况,并以此提高访问性能的方式被称为带外访问的方式。带外访问的方式可以提高性能,但代价是失去了客户端访问服务器端的透明性。传统的NFS协议只能支持带内的访问协议,虽然客户端设计起来比较简单,但是性能相对较低。在新版的NFS协议中加入了带外访问的特性,可以提高访问性能,但相应的客户端设计就变得复杂了。

对于以文件系统方式提供的存储服务来说,后台服务的设计可以通过一台服务器或多台服务器进行。如果使用一台服务器提供服务,只需要在这台服务器上提供对应的协议解析服务即可,因为这个时候所有的文件系统操作服务可以直接调用底层的本地文件系统对数据进行读写。这样,服务器端可以选择使用单机的存储系统,或者选择由多个磁盘构成的SAN作为底层的存储。这是通常的在企业内部使用的NAS服务提供方式。相比于SAN系统,这种方式提供了方便的文件系统调用接口,在提供多种协议的情况下可以支持异构的操作系统访问。这些协议都可以支持多个客户端的同时访问,可以避免SAN需要再次建立一个文件系统进行转发的额外工作。与SANFS这样的文件系统相比,这种方式的设计更具灵活性,避免了带内操作的性能下降,并且降低了实现的难度。另外,这种方式的后台存储服务也将不局限于单个节点或小规模的节点,而是可以通过大规模的集群分布式文件系统的方式将系统的总体规模扩展到非常巨大的程度。这样的规模完全克服了之前SAN方式的规模扩展性问题。另外,由于每一个节点都是完整的节点,这样的分布式文件系统不仅能够提供文件存储的服务,也可以提供大规模数据的处理能力,能够用于大数据处理。随着需要进行数据处理的数据规模的快速增长,通过分布式文件系统进行数据存储,通过前端提供NAS的访问功能,并在此基础上通过集群的计算能力支持大数据处理,成为当前标准的存储与处理方式。这部分的内容将在下面进行详细的设计与讨论。