Author: Ma, Guolai.
文件系统是操作系统用来组织磁盘文件的方法和数据结构。传统的文件系统指各种UNIX平台的文件系统,包括UFS、FFS、EXT2、XFS等,这些文件系统都是单机文件系统,也称本地文件系统。随着网络的兴起,为了解决资源共享问题,出现了分布式文件系统。分布式文件系统是指文件系统管理的物理存储资源不一定直接连接在本地节点上,而是通过计算机网络与节点相连。本文由简单地回顾本地文件系统入手,然后依次介绍了NFS、HDFS、TFS和XFS这四个分布式文件系统。接着,从体系结构、一致性、容错性等方面比较了各个分布式文件系统的异同。最后,基于四个系统的比较做出概要性的总结。
【关键字】分布式文件系统,NFS,HDFS,TFS,XFS
最初的分布式文件系统应用发生在20世纪70年代,之后逐渐扩展到各个领域。从早期 的NFS到现在的HDFS,分布式文件系统在体系结构、系统规模、性能、可扩展性、可用性等方面经历了较大的变化。
文件系统是操作系统的一个重要组成部分,通过对操作系统所管理的存储空间的抽象, 向用户提供统一的、对象化的访问接口,屏蔽对物理设备的直接操作和资源管理。
根据计算环境和所提供功能的不同,文件系统可划分为四个层次,从低到高依次是:单 处理器单用户的本地文件系统,如DOS的文件系统;多处理器单用户的本地文件系统,如 OS/2的文件系统;多处理器多用户的文件系统,如UNIX的本地文件系统;多处理器多用户 的分布式文件系统。
本地文件系统(Local File System)是指文件系统管理的物理存储资源直接连接在本地节点上,处理器通过系统总线可以直接访问。分布式文件系统(Distributed File System)是指文件系统管理的物理存储资源不一定直接连接在本地节点上,而是通过计算机网络与节点 相连。高层次的文件系统都是以低层次的文件系统为基础,实现了更高级的功能。
随着层次的提高,文件系统在设计和实现方面的难度也会成倍提高。但是,现在的分布 式文件系统一般还是保持与最基本的本地文件系统几乎相同的访问接口和对象模型,这主要 是为了向用户提供向后的兼容性,同时保持原来的简单对象模型和访问接口。但这并不说明 文件系统设计和实现的难度没有增加。正是由于对用户透明地改变了结构,满足用户的需求, 以掩盖分布式文件操作的复杂性,才大大增加了分布式文件系统的实现难度。
在计算机性能不断提升的同时,计算机部件的平均价格却在不断下降。用户可以用更低 的成本,购买更好、更快、更稳定的设备。存储系统、文件系统面临的新挑战也随之而来: 如何管理更多的设备,提供更好的性能,更加有效地降低管理成本等。各种新的存储技术和 分布式文件技术层出不穷,以满足用户日益增长的需求。因此,在体系结构、一致性和安全性等方面的对比以及分析经典的和当前主流的分布式文件系统的优劣是很有必要的。
本地文件系统通常仅仅位于一个磁盘或磁盘分区上,它只能被唯一的主机访问,不能被多个主机共享。本地文件系统通常含有四类信息:
超级块:用来描述文件系统整体信息的,含有整个文件系统中数据块和 inode的相关信息;inode:用来描述文件和目录的属性和文件块在设备上的位置信息;文件内容:是用户的数据,是无结构的;目录内容:是目录项,是有结构的。
超级块通常位于磁盘(或分区)上的固定置。根据文件系统类型,可定位超级块;通过超级块可定位根目录的inode,从而可读出根目录的内容。通过在文件系统名字空间的逐级名字解析,可得到指定文件的ino。根据ino可定位文件的inode在磁盘上的位置,从而读出文件的inode。根据inode中的块映射信息,最后定位指定的文件块,从而读出或写入数据。 归结起来,单机文件系统所含的信息可以分为三类,它们是文件数据、文件系统元数据和存储元数据。
Sun Microsystems公司于1984年推出了一个在整个计算机工业中被广泛接受的远程文件存取机制 (Network File System,NFS),该机制允许在一台计算机上运行一个服务进程,使对其上的某些或所有文件都可以进行远程存取,也允许其他计算机上的应用程序对这些文件进行存取。
当使用者想用远程文件时只要使用mount命令就可把远程文件系统安装在自己的文件系统之下。通过将客户端的内核功能(使用远程文件系统)与服务器端的NFS服务器功能(它提供文件数据)相结合,NFS允许以访问任何本地文件一样的方法,包括打开(Open)、读取(Read)、写入(Write)、定位(Seek)和关闭(Close),来访问远程主机上的文件。这种文件访问对客户来说是完全透明的,并且可在各种服务器和各种主机结构上工作。
图1给出了NFS协议层与OSI模型的比较。
图1 NFS协议层与OSI模型的比较
Hadoop分布式文件系统(HDFS)被设计成适合运行在通用硬件上的分布式文件系统。它和现有的分布式文件系统有很多共同点。但同时,它和其他的分布式文件系统的区别也是很明显的。HDFS是一个高度容错性的系统,适合部署在廉价的机器上。HDFS能提供高吞吐量的数据访问,非常适合大规模数据集上的应用。而且它提供高传输率来访问应用程序的数据,适合那些有着超大数据集的应用程序。HDFS放宽了POSIX的要求这样可以流的形式访问文件系统中的数据。
TFS(Taobao File System)是一个高可扩展、高可用、高性能、面向互联网服务的分布式文件系统,主要针对海量的非结构化数据,它构筑在普通的Linux机器集群上,可为外部提供高可靠和高并发的存储访问。TFS为淘宝提供海量小文件存储,通常文件大小不超过1M,满足了淘宝对小文件存储的需求,被广泛地应用在淘宝各项应用中。它采用了HA架构和平滑扩容,保证了整个文件系统的可用性和扩展性。同时扁平化的数据组织结构,可将文件名映射到文件的物理地址,简化了文件的访问流程,一定程度上为TFS提供了良好的读写性能。
20世纪90年代初,面对广域网和大容量存储应用的需求,借鉴当时先进的高性能对称 多处理器的设计思想,加利福尼亚大学设计开发的XFS。克服了以前的分布式文件系统一般 都运行在局域网上的弱点,很好地解决了在广域网上进行缓存,以减少网络流量的难题。它所采用的多层次结构很好地利用了文件系统的局部访问的特性,无效写回缓存一致性协议,减少了网络负载。对本地主机和本地存储空间的有效利用,使它具有较好的性能。
网络文件系统采用客户——服务器体系结构(如图2所示)。客户代码被紧密地集成到内核的虚拟文件系统(VFS)中。其中,客户端主要负责处理用户对远程文件的操作请求,并把请求的内容按一定的包格式从网络发给文件所在的服务器。而服务器则接受客户端的请求,调用本机的VFS函数进行文件的实际操作,并把结果按一定格式返回给客户端。而客户端得到服务器的返回结果,把它返回给用户。
NFS背后的基本思想是:每个文件服务器都提供其本地文件系统的一个标准化的视图。换句话说,它不关心如何实现本地文件系统;每个NFS服务器都支持相同的模型。NFS带有一个通信协议,该协议允许客户访问存储在一个服务器上的文件,从而允许异构进程集合共享共用的文件系统,其中的进程可能运行于不同的操作系统和机器上。
图2 用于UNIX系统的基本NFS体系结构
HDFS采用master/slave架构。一个HDFS集群是由一个Namenode和一定数目的Datanodes组成。Namenode是一个中心服务器,负责管理文件系统的名字空间以及客户端对文件的访问。集群中的Datanode一般是一个节点一个,负责管理它所在节点上的存储(如下图所示)。HDFS暴露了文件系统的名字空间,用户能够以文件的形式在上面存储数据。从内部看,一个文件其实被分成一个或多个数据块,这些块存储在一组Datanode上。Namenode执行文件系统的名字空间操作,比如打开、关闭、重命名文件或目录。它也负责确定数据块到具体Datanode节点的映射。Datanode负责处理文件系统客户端的读写请求。在Namenode的统一调度下进行数据块的创建、删除和复制。
图3 Hadoop体系结构
Namenode和Datanode被设计成可以在普通的商用机器上运行。这些机器一般运行着GNU/Linux操作系统。HDFS采用Java语言开发,因此任何支持Java的机器都可以部署Namenode或Datanode。由于采用了可移植性极强的Java语言,使得HDFS可以部署到多种类型的机器上。一个典型的部署场景是一台机器上只运行一个Namenode实例,而集群中的其它机器分别运行一个Datanode实例。这种架构并不排斥在一台机器上运行多个Datanode,只不过这样的情况比较少见。
集群中单一Namenode的结构大大简化了系统的架构。Namenode是所有HDFS元数据的仲裁者和管理者,这样,用户数据永远不会流过Namenode。
一个TFS集群由两个NameServer节点(一主一备)和多个DataServer节点组成。这些服务程序都是作为一个用户级的程序运行在普通Linux机器上的(如图4所示)。
图4 TFS体系结构
在TFS中,将大量的小文件(实际数据文件)合并成为一个大文件,这个大文件称为块(Block), 每个Block拥有在集群内唯一的编号(Block Id), Block Id在NameServer在创建Block的时候分配, NameServer维护Block与DataServer的关系。Block中的实际数据都存储在DataServer上。而一台DataServer服务器一般会有多个独立DataServer进程存在,每个进程负责管理一个挂载点,这个挂载点一般是一个独立磁盘上的文件目录,以降低单个磁盘损坏带来的影响。
NameServer主要功能是:管理维护Block和DataServer相关信息,包括DataServer加入,退出,心跳信息,Block和DataServer的对应关系建立,解除。正常情况下,一个块会在Data Server上存在, 主NameServer负责Block的创建,删除,复制,均衡,整理, NameServer不负责实际数据的读写,实际数据的读写由DataServer完成。
DataServer主要功能是:负责实际数据的存储和读写。
同时为了考虑容灾,NameServer采用了HA结构,即两台机器互为热备,同时运行,一台为主,一台为备,主机绑定到对外vip,提供服务;当主机器宕机后,迅速将vip绑定至备份NameServer,将其切换为主机,对外提供服务。图中的Heart Agent就完成了此功能。
TFS的块大小可以通过配置项来决定,通常使用的块大小为64M。TFS的设计目标是海量小文件的存储,所以每个块中会存储许多不同的小文件。DataServer进程会给Block中的每个文件分配一个ID(File ID,该ID在每个Block中唯一),并将每个文件在Block中的信息存放在和Block对应的Index文件中。这个Index文件一般都会全部load在内存,除非出现DataServer服务器内存和集群中所存放文件平均大小不匹配的情况。
另外,还可以部署一个对等的TFS集群,作为当前集群的辅集群。辅集群不提供来自应用的写入,只接受来自主集群的写入。当前主集群的每个数据变更操作都会重放至辅集群。辅集群也可以提供对外的读,并且在主集群出现故障的时候,可以接管主集群的工作。
XFS的与众不同之处在于它的无服务器设计,整个文件系统分布于多台机器,包括客户(如图5所示)。这种方法完全不同于大多数其他文件系统,后者通常以集中式的方式组织,即使系统中存在 多个用于发送和复制文件的服务器,像AFS和Coda。
XFS设计为运行在高速局域网之上,即其中的机器通过高速连接互连。很多现代网络都 满足这一要求,特别是工作站的集群。通过将数据和控制完全地分布于局域网内的机器,XFS的设计人员旨在达到比使用(可能是复制的)文件服务器的传统分布式文件系统更高的可扩展性和容错性。
图5 XFS进程在多台机器上的一种典型分布
在XFS的体系结构中,有三种不同类型的进程。存储服务器是负责存储文件的某些部分的进程。多个存储服务器共同地实现虚拟磁盘的阵列,此阵列类似于以RAID形式实现的磁盘阵列。元数据管理器是负责记录文件数据块的实际存储位置的进程。注意,同一文件的数据块可能散布于多个存储服务器,管理器将客户的请求转发到适当的存储服务器。由此看来,元数据管理器作为文件数据块的定义服务器运行。最后XFS的客户是接受用户请求以执行文件操作的进程,每个客户有缓存的能力,并且可以向其他客户提供被缓存的数据。
XFS的基本设计原则是任何机器都可以担当客户、管理器和服务器的角色。在完全对称 的系统中,每台机器都运行这三个进程。但是,使用专用机器运行存储服务器,而其他机器运行客户或管理器进程也是可能的。
在NFS中,客户与服务器之间的所有通信都遵循开放式网络计算RPC协议以及表示编组数据的标准。每个NFS操作都可以被实现为对文件服务器的单一远程过程调用。RPC使用和传统程序一样的过程抽象,只是它允许一个过程的边界跨越两台计算机。图6是一个远程过程调用模型。
图6 远程过程调用模型
远程过程调用模型主要来自于传统编程语言中的过程调用机制。所谓过程调用,是一种函数或过程的使用方法,它将控制权和相关的数据由进程的一部分转移到另一部分,一部分完成任务后将控制权和运算结果返回给原来的部分。过程调用提供了一个强有力的抽象,它允许程序员将一个程序划分为一些小的、可管理的、易于理解的片段。它可以给出程序执行的概念性模型的简单明了的实现。
事实上,在NFS版本4之前,客户通过保持请求相对简单来尽可能地简化服务器工作。例如,客户为了第一次从一个文件中读取数据,通常必须先使用lookup操作查找文件句柄,然后它才能发出一个read请求,如图7所示。
图7 在NFS版本3中,从文件中读取数据 图8 在NFS版本4中,使用复合过程读取数据
这种方法需要两个连续的RPC。如果在光与系统中使用NFS,这种方法显然存在缺点。此时,第二个RPC的额外延迟可能导致性能降级。为了解决这些问题,NFS版本4支持符合过程,可以通过它把多个RPC组合成单个请求。如图8所示。
所有的HDFS通讯协议都是建立在TCP/IP协议之上。客户端通过一个可配置的TCP端口连接到Namenode,通过ClientProtocol协议与Namenode交互。而Datanode使用DatanodeProtocol协议与Namenode交互。一个远程过程调用(RPC)模型被抽象出来封装ClientProtocol和DatanodeProtocol协议。在设计上,Namenode不会主动发起RPC,而是响应来自客户端或 Datanode 的RPC请求。
原有TFS集群运行一定时间后,集群容量不足,此时需要对TFS集群扩容。由于DataServer与NameServer之间使用心跳机制通信,如果系统扩容,只需要将相应数量的新DataServer服务器部署好应用程序后启动即可。这些DataServer服务器会向NameServer进行心跳汇报。NameServer会根据DataServer容量的比率和DataServer的负载决定新数据写往哪台DataServer的服务器。根据写入策略,容量较小,负载较轻的服务器新数据写入的概率会比较高。同时,在集群负载比较轻的时候,NameServer会对DataServer上的Block进行均衡,使所有DataServer的容量尽早达到均衡。
进行均衡计划时,首先计算每台机器应拥有的Blocks平均数量,然后将机器划分为两堆,一堆是超过平均数量的,作为移动源;一类是低于平均数量的,作为移动目的。
移动目的的选择:首先一个Block的移动的源和目的,应该保持在同一网段内,也就是要与另外的Block不同网段;另外,在作为目的的一定机器内,优先选择同机器的源到目的之间移动,也就是同台DataServer服务器中的不同DataServer进程。
当有服务器故障或者下线退出时(单个集群内的不同网段机器不能同时退出),不影响TFS的服务。此时NameServer会检测到备份数减少的Block,对这些Block重新进行数据复制。
在创建复制计划时,一次要复制多个Block, 每个Block的复制源和目的都要尽可能的不同,并且保证每个Block在不同的子网段内。因此采用轮换选择(round robin)算法,并结合加权平均。
由于DataServer之间的通信是主要发生在数据写入转发的时候和数据复制的时候,集群扩容基本没有影响。假设一个Block为64M,数量级为1PB。那么NameServer上会有1 * 1024 * 1024 * 1024 / 64 = 16.7M个Block。假设每个Block的元数据大小为0.1K,则占用内存不到2G。
最初XFS中的所有通信都是使用RPC处理的,但是后来由于某些原因,XFS放弃了这种方法,最重要的原因是其性能较低。RPC的另一个问题是它通常假设通信是peer-to-peer的。因为数据和控制完全分布于多台机器,所以单一客户的请求可能设计一连串进程间的通信。RPC服务器必须显示地记录未完成的请求,并把输入的响应匹配到适当的请求。因而,简单的阻塞机制是行不通的。
由于以上原因,XFS中的通信被活动消息取代。在活动消息中,接收方的处理程序以及 调用它的必要参数都是指定的。消息到达时,处理程序被直接调用,运行直至程序完成。处 理程序执行时,不能传递其他消息。这种方法的优点体现在效率方面,但是活动消息使通信的设计变得更加复杂。比如,不允许阻塞处理程序。处理程序还应该相对较小,这是因为处理程序的执行妨碍了处理程序所在主机的其他网络通信。
NFS命名模型下面的基本思想是:允许客户完全透明地访问服务器维护的远程文件系统。这种透明性是通过使客户能够在它本身的本地文件系统中挂载一个远程文件系统实现的。如图9所示。
NFS允许客户不挂载整个文件系统,而只挂载文件系统的一部分。当服务器允许其他客户使用一个目录及该目录中的项目时,称该服务器输出那个目录。一个输出目录可以由客户挂载到其本地名称空间中。
图9 在NFS中挂载远程文件系统(的一部分)
一个NFS服务器自身可以挂载其他服务器输出的目录。但是,它不能再将这些目录输出给它自己的客户。作为替代,客户必须显式地从维护目录的服务器那里挂载该目录,如图10所示。加入这一限制的部分原因是出于简单性考虑。如果服务器可以输出它从其他服务器挂载的目录,那么它就可能返回包含服务器标识符的特殊文件句柄。NFS不支持这种文件句柄。
图10 从NFS中的多个服务器挂载嵌套的目录
HDFS支持传统的层次型文件组织结构。用户或者应用程序可以创建目录,然后将文件保存在这些目录里。文件系统名字空间的层次结构和大多数现有的文件系统类似:用户可以创建、删除、移动或重命名文件。当前,HDFS不支持用户磁盘配额和访问权限控制,也不支持硬链接和软链接。但是HDFS架构并不妨碍实现这些特性。
Namenode负责维护文件系统的名字空间,任何对文件系统名字空间或属性的修改都将被Namenode记录下来。应用程序可以设置HDFS保存的文件的副本数目。文件副本的数目称为文件的副本系数,这个信息也是由Namenode保存的。
TFS的文件名由块号和文件号通过某种对应关系组成,最大长度为18字节。文件名固定以T开始,第二字节为该集群的编号(可以在配置项中指定,取值范围 1~9)。余下的字节由Block ID和File ID通过一定的编码方式得到。文件名由客户端程序进行编码和解码,它映射方式如下图所示:
图11 文件名映射方式
TFS客户程序在读文件的时候通过将文件名转换为Block ID和File ID信息,然后可以在NameServer取得该块所在DataServer信息(如果客户端有该Block与DataServer的缓存,则直接从缓存中取),然后与DataServer进行读取操作。
除了使用各种系统范围的标识符来搜索管理器、块、inode等的位置之外,XFS的命名没有其他特殊之处。表1总结了XFS所用的各种标识符和数据结构。
表1 XFS所用的各种标识符和数据结构
数据结构 |
描述 |
管理器映射 |
将文件 ID 映射到管理器 |
Imap |
将文件 ID 映射到文件的 inode 的日志地址 |
Inode |
将块号(即,位移)映射到块的日志地址 |
文件标识符 |
索引管理器映射 |
文件目录 |
将文件名映射为文件标识符 |
日志地址 |
带区组 ID、记录段 ID 和记录段位移的三元组 |
带区组映射 |
将带区组 ID 映射为存储服务器的列表 |
NFS版本4实质上只提供4种与锁相关的操作,如图12所示。NFS对读操作锁和写操作锁加以区分。如果多个客户只读取数据,那么它们可以同时访问一个文件的相同部分。为了获取修改文件的某个部分的独占访问权,需要使用写操作锁。
图12 NFS版本4中关于文件锁定的操作
被授予的锁在一段指定(有服务器决定)内有效。换句话说,它们都具有关联的租约。除非客户更新授予其锁上的租约,否则服务器会自动删除它的锁。我们将看到,服务器端提供的其他资源也采用这种方法,它有助于故障后的恢复。客户使用renew操作来请求服务器更新其锁上的租约。
相对版本3,NFS版本4 解决了一些有关一致性的问题,但它实质上仍以实现相关的方式处理缓存的一致性。图13显示了NFS假定的通用缓存模型。每个客户都可以有一个存储器缓存,它包含先前从服务器读取的数据。另外,客户端还有一个磁盘缓存,它作为存储缓存的扩展,并使用相同的一致性参数。
图13 NFS中的客户端缓存
NFS版本4支持两种缓存文件数据的方法。最简单的方法是当客户打开文件时,将它从服务器获得的数据缓存起来,并把这些数据作为各种read操作的结构。另外,write操作也可以在缓存中执行。客户关闭文件时,NFS要求如果文件被修改,那么必须把缓存的数据送回服务器。
在NFS版本4中,在打开文件时,服务器可以将它的某些权限委托给客户。开放式委托发生在客户机被允许在本地处理来自同一机器的其他客户的open和close操作时。将文件委托给客户的一个重要后果是:服务器需要有能力撤销这种委托,如图14所示。
图14 使用NFS版本4的回调机制撤销
HDFS应用需要一个“一次写入多次读取”的文件访问模型。一个文件经过创建、写入和关闭之后就不需要改变。这一假设简化了数据一致性问题,并且使高吞吐量的数据访问成为可能。Map/Reduce应用或者网络爬虫应用都非常适合这个模型。目前还有计划在将来扩充这个模型,使之支持文件的附加写操作。
HDFS被设计成能够在一个大集群中跨机器可靠地存储超大文件。它将每个文件存储成一系列的数据块,除了最后一个,所有的数据块都是同样大小的。为了容错,文件的所有数据块都会有副本。每个文件的数据块大小和副本系数都是可配置的。应用程序可以指定某个文件的副本数目。副本系数可以在文件创建的时候指定,也可以在之后改变。HDFS中的文件都是一次性写入的,并且严格要求在任何时候只能有一个写入者。
Namenode全权管理数据块的复制,它周期性地从集群中的每个Datanode接收心跳信号和块状态报告。接收到心跳信号意味着该Datanode节点工作正常。块状态报告包含了一个该Datanode上所有数据块的列表。
当客户端向HDFS文件写入数据的时候,一开始是写到本地临时文件中。假设该文件的副本系数设置为3,当本地临时文件累积到一个数据块的大小时,客户端会从Namenode获取一个Datanode列表用于存放副本。然后客户端开始向第一个Datanode传输数据,第一个Datanode一小部分一小部分(4KB)地接收数据,将每一部分写入本地仓库,并同时传输该部分到列表中第二个Datanode节点。第二个Datanode也是这样,一小部分一小部分地接收数据,写入本地仓库,并同时传给第三个Datanode。最后,第三个Datanode接收数据并存储在本地。因此,Datanode能流水线式地从前一个节点接收数据,并在同时转发给下一个节点,数据以流水线的方式从前一个Datanode复制到下一个(如下图所示)。
图15 HDFS块复制
TFS系统中,NameServer会保证一个文件有多个副本存储于不同的DataServer上以保证冗余。当由于DataServer服务器宕机或由于其他原因退出系统导致某些文件副本数量下降时,NameServer将会调度新的DataServer节点存储文件备份。同样为了保证数据一致性,当写入一个文件时,只有所有参与的DataServer均写入成功时,该操作才算成功。TFS的写操作数据流图如下所示:
图16 TFS写操作数据流图
客户端首先向NameServer发起写请求,NameServer需要根据DataServer上的可写块,容量和负载加权平均来选择一个可写的Block。并且在该Block所在的多个DataServer中选择一个作为写入的master,这个选择过程也需要根据DataServer的负载以及当前作为master的次数来计算,使得每个DataServer作为master的机会均等。master一段选定,除非master宕机,不会更换,一旦master宕机,需要在剩余的DataServer中选择新的master。返回一个DataServer列表。
客户端向master DataServer开始数据写入操作。master server将数据传输为其他的DataServer节点,只有当所有DataServer节点写入均成功时,master server才会向NameServer和客户端返回操作成功的信息。
XFS的客户维护本地高速缓存。其一致性方案类似于Coda的一致性方案,只是它缓存的是数据块,而不是整个文件。也就是说,当一个客户想要写入一块数据时,它联系该数据 块所属文件的管理器,并请求写权限。管理器首先使由其他客户缓存的该数据块的所有拷贝 无效,然后,它授予该客户写权限。这样,管理器就记录了数据块被缓存的位置,以及哪个 客户被授予了写权限。后者也被称为当前所有者。
只要所有者拥有一个数据块的写权限,它不需要联系管理器就可以使用它的缓存拷贝来 执行更新操作。当另一个客户想要访问该数据块时,所有者的写权限被撤销。此时,清洗当 前所有者的高速缓存,并存储该数据块,直到它可以被转发到一个存储服务器。另外,该数 据块被发送到新的客户,而这个新的客户称为写一个所有者。
XFS进一步实现了协作缓存(collaborative caching)。在该方法中,每当客户想要访问一 个数据块时,它联系适当的管理器,如上所述。但是,管理器不是在存储服务器上定位所请 求的数据块,而是先检查当前是否存在其他已经缓存了所请求数据块的客户。如果存在这样 的客户,那么它就从高速缓存获取一份拷贝,并将其返回给提出请求的客户。
副本的存放是HDFS可靠性和性能的关键。优化的副本存放策略是HDFS区分于其他大部分分布式文件系统的重要特性。这种特性需要做大量的调优,并需要经验的积累。HDFS采用一种称为机架感知(rack-aware)的策略来改进数据的可靠性、可用性和网络带宽的利用率。目前实现的副本存放策略只是在这个方向上的第一步。实现这个策略的短期目标是验证它在生产环境下的有效性,观察它的行为,为实现更先进的策略打下测试和研究的基础。
大型HDFS实例一般运行在跨越多个机架的计算机组成的集群上,不同机架上的两台机器之间的通讯需要经过交换机。在大多数情况下,同一个机架内的两台机器间的带宽会比不同机架的两台机器间的带宽大。
通过一个机架感知的过程,Namenode可以确定每个Datanode所属的机架id。一个简单但没有优化的策略就是将副本存放在不同的机架上。这样可以有效防止当整个机架失效时数据的丢失,并且允许读数据的时候充分利用多个机架的带宽。这种策略设置可以将副本均匀分布在集群中,有利于当组件失效情况下的负载均衡。但是,因为这种策略的一个写操作需要传输数据块到多个机架,这增加了写的代价。
在大多数情况下,副本系数是3,HDFS的存放策略是将一个副本存放在本地机架的节点上,一个副本放在同一机架的另一个节点上,最后一个副本放在不同机架的节点上。这种策略减少了机架间的数据传输,这就提高了写操作的效率。机架的错误远远比节点的错误少,所以这个策略不会影响到数据的可靠性和可用性。于此同时,因为数据块只放在两个(不是三个)不同的机架上,所以此策略减少了读取数据时需要的网络传输总带宽。在这种策略下,副本并不是均匀分布在不同的机架上。三分之一的副本在一个节点上,三分之二的副本在一个机架上,其他副本均匀分布在剩下的机架中,这一策略在不损害数据可靠性和读取性能的情况下改进了写的性能。
HDFS的主要目标就是即使在出错的情况下也要保证数据存储的可靠性。常见的三种出错情况是:Namenode出错, Datanode出错和网络割裂(network partitions)。
每个Datanode节点周期性地向Namenode发送心跳信号。网络割裂可能导致一部分Datanode跟Namenode失去联系。Namenode通过心跳信号的缺失来检测这一情况,并将这些近期不再发送心跳信号Datanode标记为宕机,不会再将新的IO请求发给它们。任何存储在宕机Datanode上的数据将不再有效。Datanode的宕机可能会引起一些数据块的副本系数低于指定值,Namenode不断地检测这些需要复制的数据块,一旦发现就启动复制操作。在下列情况下,可能需要重新复制:某个Datanode节点失效,某个副本遭到损坏,Datanode上的硬盘错误,或者文件的副本系数增大。
图17 Name Server容灾机制
结构中有两个NameServer, 在同一时刻,只有一个为主,一个为备。主NameServer是对外提供服务的机器,并接管了对外服务的IP地址;备NameServer维护元数据状态,一旦主NameServer停止服务,会马上将自身切换为主,绑定对外IP地址,继续提供服务。
通过将存储服务器实现为保留冗余信息的带区组,使得XFS的可用性比传统方法的可 用性要高。每当一个单独的服务器崩溃时,它可以通过获取其他服务器上的奇偶校验分段来 恢复分段。如果奇偶校验分段丢失了,那么它可以容易地从现有的分段计算出来。但是如果 统一组内的多个服务器崩溃了,那么需要采取特殊的措施,但是这些措施还未被实现。
管理器的恢复主要是通过不时地对管理器当前持有的数据设置检查点得到支持。一个难 以处理的问题是恢复管理器的映射。设置检查点对此有帮助,但是仍需考虑检查点后更改。 为此,各个客户记录它们自最后一个检查点以来向管理器发送的更新。这样,管理器可以请 求客户重放一个检查点之后的更新,从而使得它的imap进入与存储服务器上的信息一致的 状态。
NFS的安全性主要集中于客户和服务器之间的通信。除了安全RPC之外,控制文件访问也是十分必要的。这是通过NFS中的访问控制文件属性处理的,文件服务器负责验证其客户的访问权限。结合了安全RPC的NFS安全性体系结构如图18所示。
图18 NFS安全性体系结构
因为NFS位于RPC系统的层次之上,所以建立NFS中的安全信道的关键在于建立安全RPC。在NFS版本4之前,安全RPC仅意味着负责进行身份认证。RPCSEC_GSS基于安全性服务的标准接口,该接口称为GSS-API,(Linn 1997)中完整地描述了此接口。RPCSEC_GSS所在的层在此接口所在的层之上,图19显示了其组织结构。
图19 NFS版本4中的安全RPC
Namenode启动后会进入一个称为安全模式的特殊状态。处于安全模式的Namenode是不会进行数据块的复制的。Namenode从所有的Datanode接收心跳信号和块状态报告。块状态报告包括了某个Datanode所有的数据块列表。每个数据块都有一个指定的最小副本数。当Namenode检测确认某个数据块的副本数目达到这个最小值,那么该数据块就会被认为是副本安全(safely replicated)的;在一定百分比(这个参数可配置)的数据块被Namenode检测确认是安全之后(加上一个额外的30秒等待时间),Namenode将退出安全模式状态。接下来它会确定还有哪些数据块的副本没有达到指定数目,并将这些数据块复制到其他Datanode上。
XFS仅对安全性提供最低限度的支持。除了实现常见的访问控制机制外,XFS要求客户、 管理器和存储服务器运行于可信任的机器上以实施安全性。但是,它提供了一种让不被信任 的NFS客户使用安全RPC访问一些XFS机器的简单措施。实际上,NFS客户使用安全RPC联系XFS客户。因此,XFS客户将作为那个NFS客户的NFS服务器。
XFS是一种采用了无服务方式以提供可扩展的文件服务的机群文件系统。同zebra一样,XFS集成了存储分组结构和日志结构,并且也实现了数据存储于元数据管理的彼此分离。XFS 通过全部分布数据存储于元数据管理的功能减少了集中的瓶颈。为了获得更高的性能,XFS采用了合作缓存,一种通过各客户缓存的协调合作来替代传统的集中的服务端缓存。在XFS 中,任何机器都可以缓存、存储或则控制任意的数据块,这种方式可以提供比传统文件系统结构更好的性能和可扩展性。
XFS的一个主要的特点是它的合作缓存的算法,即是N-Chance算法。 这种算法动态地把每个客户端的缓存分开成块,以提供给当地的和那些存储在合作缓存的应用程序的应用。算法的置换机制是综合应用了当地LRU信息和重复避免(duplicate avoidance)以决定所最应该置换的块。实际上,XFS所应用的缓存结构与远端缓存结构以及Feeley描述的全局存储服务(GMS)具有相类似的构想。GMS 比N-Chance算法更具有通用性,但它没有提供一致性机制并且依靠一种集中式的算法来决定块的置换。Sarkar and Hartman提出了一 种基于提示(hint-based)的合作缓存方式,这种方式可以减少客户机在通过提示调用和置换块是对管理者的依靠性。实验表明这种方式可以在增加少量的负载的情况下获得同XFS所相似的效果。但是它有一个缺点是它必须维护在文件级粒度下的缓存一致性,否则可能导致在某些情况下的共享错误问题(false-sharing problem)。
分布式文件系统已经发展了近30年的,并且取得了巨大的成功。本文主要介绍了4种分布式文件系统,并在体系结构、一致性和容错性等方面对其进行比较。
分布式文件系统通常按照客户——服务器模型组织,使用端缓存和对复制的支持来满足可扩展性的需求。另外,为了实现高可用性,需要使用缓存和复制。
使分布式文件系统与非分布式文件系统不同的是共享文件的语义。理想情况下,文件系统可以使客户总是读取最近写入文件的数据。在分布式系统中实现这些UNIX文件共享语义是非常困难的。在服务器控制所有操作的情况下,可以提供真正的UNIX语义,但是这样会造成可扩展性问题。
为了达到可接受的性能,分布式文件系统通常允许客户缓存完整的文件。但是只存储文件的大部分数据也是可能的。一旦文已经打开,并(不分的)传送到客户,则所有操作都在客户端本地执行。当文件再次被关闭时,客户向服务器返回所有更新。另外,支持块缓存的话可以将它与回写式高速缓存一致性协议结合。
通常不是直接在传输层上建立分布式文件系统,而假设存一个RPC层,使所有操作都可以简单地表示为文件服务器的RPC,而不必使用原始的消息传送操作。RPC层最好提供最多一次调用的语义。否则,这些语义将不得作为文件系统层的一部分而被显式地实现,像NFS。
安全性是任何分布式系统都不可忽视的方面。NFS本身不提供任何安全性机制,但是,它实现了标准化接口,这使得它可以用不同的现有安全性系统,比如Kerberos。而其他文件系统则提出了自己的安全性机制,这些系统使用RPC来进行身份验证。
从分析中也可以看出一些发展趋势:体系结构的研究逐渐成熟,表现在不同文件系统体结趋于一致;系统设计的策略基本一致,如采用专用服务器方式等;每个系统在设计的细节上各自采用了很多特有的先进技术,也都取得了很好的性能和扩展性。
* 本文版权和/或知识产权归eBay Inc所有。如需引述,请和联系我们[email protected]。本文旨在进行学术探讨交流,如您认为某些信息侵犯您的合法权益,请联系我们[email protected],并在通知中列明国家法律法规要求的必要信息,我们在收到您的通知后将根据国家法律法规尽快采取措施。