1、第五章分布式文件系统第 五 章 分布式文件系统对任何分布式系统来说,文件系统都是其中的一个关键组成部分。同在单处理机系统中一样,分布式系统中文件系统的工作也是存储程序和数据,使它们在需要时可用。分布式文件系统在许多方面类似于传统的文件系统,在这里就不再赘述了。相反地,我们将着重讨论分布式文件系统不同于集中式文件系统的那些方面。首先,在分布式系统中,区分文件服务和文件服务器这两个概念是非常重要的。文件服务是文件系统提供给客户内容的详细说明。它描述了可用的原语,以及原语所需的参数和执行的动作。对于客户来说,文件服务精确地定义了他们所期望的服务,但并不涉及这些服务是如何实现的。实际上,文件服务说明了
2、文件系统对客户的接口。相反,文件服务器是运行在某台机器上的一个有助于实现文件服务的进程。一个系统可以有一个或多个文件服务器。特别是,客户可能不知道有多少个文件服务器以及每个服务器的位置和功能。他们所知道的是当它调用文件服务中的具体过程时,所要求的工作以某种方式执行,并返回所需的结果。实际上,客户甚至不知道文件服务是分布的。理想情况下,它可能看上去和通常的单处理机文件系统一样。由于文件服务器通常仅仅是运行在某台机器上的一个用户进程(有时是一个核心过程),所以一个系统可包含多台文件服务器,每台服务器提供不同的文件服务。例如,一个分布式系统可以有两个文件服务器,分别提供UNIX文件服务和MS-DOS
3、文件服务,每个用户进程可以分别地使用适合它的文件服务器。在那种方式下,分布式系统的终端就可能有多个窗口,一些UNIX程序运行在一些窗口,而一些MS-DOS程序运行在另一些窗口而互不冲突。服务器是否提供特殊的文件服务,如UNIX或MS-DOS,或者更多的一般性服务取决于系统设计者。可用的文件服务的类型和数量甚至可以随着系统的发展而改变。5.1 分布式文件系统设计分布式文件系统通常包括两个截然不同的部分:真正的文件服务和目录服务。前者涉及单个文件上的操作,例如读,写和追加,而后者涉及创建和管理目录,在目录中增加和删除文件等。本节我们讨论真文件服务接口,下一节再讨论目录服务接口。511 文件服务接口
4、无论是在单处理机系统中还是在分布式系统中,对于任何文件服务,最基本的问题是:什么是文件? 在许多系统中,如UNIX和MS-DOS,文件是一个未经解释的字节序列。文件中信息的含义和结构完全取决于应用程序,操作系统对此不感兴趣。然而,在主机上存在着多种类型的文件,每种类型的文件都有各自不同的特性。一个文件可以组织成一个记录系列,例如,根据操作系统要求来读写一个特定的记录。这个记录通常由给定它的记录号(即在文件中的位置)或者某一字段的值来确定。在后一种情况下,操作系统既可以把文件作为B型树来保存,也可以把文件作为其它合适的数据结构来保存,或者使用哈希表来迅速定位记录。由于大多数分布式系统都是用作UN
5、IX或者MS-DOS环境,所以大部分文件服务器都支持文件作为一字节序列的概念,而不支持文件作为一段关键字的记录序列的概念。文件有多个属性,这些属性都是关于文件的一部分信息,而不是文件本身的一部分。典型的属性有:所有者、大小、创建日期和访问权限。文件服务通常提供读写某些属性的原语,例如,有可能改变访问权限而不用改变文件大小(除非对文件追加数据)。在少数高级系统中,可以建立和使用除标准属性以外的用户自定义属性。文件模型的另一个重要方面是文件创建后能否被修改,通常是可以的。但在某些分布式系统中,对文件的操作只有CREATE和READ。一旦文件创建了,就不能改变它。这样的文件称为是不可变的(immut
6、able)。保持文件的不可变性,使得支持文件高速缓存和复制的变得更为容易,因为它消除了有关文件改变时必须修改所有文件拷贝的全部问题。分布式系统的保护基本上使用了与单处理机系统相同的技术:权能(capability)和存取控制表。就权能而言,每个用户拥有访问每个对象的某种门票,称作权能。权能指定了允许的访问类型(例如,允许读但不允许写)。所有的存取控制表模式把每个文件与可以访问它的用户以及访问方式联系起来。UNIX模式就是一个简化了的存取控制表,它通过使用二进制位来分别控制所有者、所有者组、以及其他每个人对每个文件的读、写、以及运行。根据是否支持上载/下载模(upload/download)式或
7、远程访问模式 文件服务可以分成两大类。在上载/下载模式中,如图5-1(a)所示,文件服务只提供两种主要的操作:读文件和写文件。前一个操作是把整个文件从一个文件服务器传送到提出请求的客户;后一个操作是把整个文件从客户传送到服务器。因此这种概念模式是在任一方向上传送整个文件。这些文件可以存储在内存或本地的硬盘,视需要而定。 图 5-1 (a) 上载/下载模式; (b) 远程存取模式 上载/下载的优点是概念简单。应用程序取得它们所需的文件,然后在本地使用它们。任何修改过的文件或新创建的文件在程序结束时都要将它回写。使用这种模式不需要掌握复杂的文件接口,而且,整个文件传送也是高效的。但是,客户端必须具
8、有足够大的存储空间来存储所需的所有文件。而且,如果只需要文件的一小部分,移动整个文件是很浪费的。 文件服务的另一种类型是远程访问模式, 如图5-1(b)所示。在这种模式中,文件服务提供了大量的操作用于打开和关闭文件,读写文件的一部分,在文件中来回移动(LSEEK),检查和改变文件属性等等。而在上载/下载模式中,文件服务只提供物理存储和传送,在这里文件系统运行在服务器上而不是运行在客户端。远程存取模式的优点是在客户端不需要很大的空间,当仅需要文件的一小部分时,不需要传送整个文件。5.1.2 目录服务器接口文件服务的另一部分是目录服务,它提供诸如创建和删除目录,命名和重命名文件以及把文件从一个目录
9、移动到另一个目录等操作。目录服务的性质并不依赖于单个文件是整体传送还是远程访问。目录服务定义了构成文件(目录)名的某种字母表和语法。文件名通常是从1到某一最大数的字母,数字和某些特殊字符。有些系统把文件名分成两个部分,通常用一个点分开,如用prog.c表示一个c程序或表示一个文本文件。文件名的第二部分叫作文件扩展,标识文件的类型。其它的系统使用一个显式属性来达到此目的,而不是在文件名上添加一个扩展名。所有的分布式系统都允许目录包含子目录,这使得用户可以把相关文件组合到一起。相应地,系统提供了创建和删除目录的操作,也提供了在目录中插入、移动和查找文件的操作。通常,每个子目录包含一个项目的所有文件
10、,如一个大程序或文档 (如一本书) 。当显示该(子)目录时,只显示相关的文件,无关文件在其它(子)目录中,这样就不致使显示列表凌乱。子目录可以包含它们自己的子目录,以此类推,这样就形成一棵目录树,通常称为分层文件系统。图5-2(a)表示了一棵有五个目录的树。在某些系统中,可以对任意目录建立连接或指针。这种连接和指针可以放在任一目录中,使得不仅可以按树结构组织目录,而且可以把目录组织成更强有力的任意目录图。在分布式系统中,树和图的区别特别重要。由图5-2(b)的目录图可见难点的性质。在这张图中,目录D连接到目录 B上。当删除A到B的连接时,就出现问题了.在树型层次结构中,仅当目录为空时,才能删除
11、指向该目录的连接。在目录图中,一个目录只要存在至少另一条链接就可以删除指向该目录的链接。通过保存一个参考计数,如图5-2(b)中的每个目录的右上角所示,就可以确定什么时候删除的链接是最后一个链接。 图 5-2 (a) 包含在一台机器中的目录树 (b) 在两台机器中的目录图 删除A到B的连接之后,B的参考计数从2减为1,这在理论上是行得通的。然而,现在从文件系统(A)的根已不能达到B。B、D和E三个目录以及它们所有的文件实际上是孤立了。这样的问题在集中式系统中也存在,但在分布式系统中显得更加严重。如果所有内容都在一台机器上,虽然花销有点昂贵,但是当发现孤立目录时,因为所有的信息都在一个地方,就可
12、以停止所有的文件活动。并且从图的根开始遍历,标记所有可达到的目录。当这个过程结束时,所有未标记的目录便认为是不可达到的。在分布式系统中,涉及到多台机器,不能停止所有的活动,因此得到一个“瞬态图” 即使有可能也很困难。在设计任何分布式系统时,一个关键的问题是:是否全部机器(和进程)都应该具有完全相同的分层目录结构视图。为说明这一问题,给出一个例子(参考图5-3)。在图5-3(a)中我们给出了两个文件服务器,每个文件服务器有三个目录和一些文件;在图5-3(b)中,我们有一个系统,其中所有的客户(和其它机器)具有相同的分布式文件系统视图,如果路径/D/E/x在一台机器上有效,则在所有的机器上都有效。
13、相反,在图5-3(c)中,不同的机器可能具有不同的文件系统视图。重复前面的例子,路径/D/E/x在客户1可能是有效的,而在客户2上可能是无效的。在通过远程安装管理多个文件服务器的系统中,图5-3(c)是一个标准。其实现是灵活且简单的,但其缺点是不能使整个系统的行为变成像一个单个过时的分时系统一样。在分时系统中,对任何进程,文件系统看起来都是一样的(即5-3(b)所示的模型)。这个特性使得系统容易编程和理解。 图5-3 (a)两文件服务器。方框是目录,圆圈是文件; (b)一个所有用户有同样文件系统图的系统; (c) 一个不同的客户有不同的文件系统的系统基于此,一个密切相关的问题是,是否存在一个全
14、局根目录,所有的机器都认为其为根。设置全局根目录的一个方法是使这个根只包含每个服务器的一个入口。在这种情况下,路径的形式为:/服务器/路径,虽有它自身的缺点,但至少在系统中任何地方都是一样的。命名透明性基于此,这种命名形成的主要问题就是:它不是完全透明的。在上下文中有两种形式的透明性是相关的,且有必要加以区分。第一种是位置透明性,是指路径名并不能对文件(或其它对象)存储位置给出任何提示。像路径/server1/dir1/dir2/x说明 x位于服务器1上,但是它并没有说明服务器1的位置。服务器在网络中可以自由地移动到任何它想去的地方而无需改变路径名。因此,这样的系统具有位置透明性。然而,假设文
15、件x非常大而且服务器1上的空间又很紧张。进一步,假设在服务器2上有足够的空间。系统很可能自动地把文件x移到服务器2上。不幸的是当所有路径名的第一部分是服务器时,尽管dir1和dir2在两个服务器上都存在,但系统不能自动地把文件移动到其它的服务器上去。问题在于自动的移动文件要把路径名由/server1/dir1/dir2/x变为/server2/dir1/dir2/x。如果路径改变,具有前一个路径字符串的程序将停止工作。在一个系统中文件能够移动而无需改变其文件名,这样的系统称之为具有位置独立性。一个明确把机器或服务器名嵌入路径名的分布式系统不是位置独立的系统。基于远程安装的系统也不具备位置独立性
16、,因为它不可能把一个文件从一个文件组(安装单元)移动到另一个文件组并仍可使用旧路径名。位置独立性是不容易实现的,但它是分布式系统所期望拥有的一个特性。总结前面所述的内容,在分布式系统中用于文件和目录命名有以下三种常见的方法:1. 机器+路径命名,如/machine/path或machine:path。2. 安装远程文件系统到本地文件分层结构。3. 一个在所有机器上看上去都一样的单个名字空间。前两种方法容易实现,特别是作为一种并非为分布式系统设计的连接现存系统的方法。第3种方法的实现困难并且需要仔细设计,但如果要实现使分布式系统像单个计算机一样工作的目标,这种方法是需要的。两级命名大多数分布式系
17、统都是使用某种形式的两级命名。文件(和其它对象)具有符号名(比如,prog.c),供用户使用,但它们还可具有内部的二进制名供系统自己使用。目录实际上起的作用是提供这两个命名层次之间的一个变换(映射)。用户和程序使用符号(ASCII)名是很方便的,但在系统内部使用,这些名字太长且不方便。这样当用户打开一个文件或另外引用一个符号名时,系统将立即在适当的目录中查找符号名以得到其用于定位该文件二进制名。有时,二进制名对于用户是可见的,而有时候是不可见的。二进制名的特性随系统的不同而有显著地变化。在一个由多个文件服务器组成的系统中,其中每个文件服务器都是自含的(即它不引用其它文件服务器中目录或文件 ),
18、二进制名可以像在UNIX系统中一样仅仅是一个局部的i-节点数。一个更常见的命名模式是让这个二进制名同时指明服务器和在它上面的一个具体文件。这种方法允许一个服务器上的目录拥有一个不同的服务器上的文件。完成此功能的有时被首选的另一种方法是使用符号连接。符号连接是一个目录项目,它映射到 一个(服务器,文件名)字符串上,此串可以在为查找其二进制名而命名的服务器上查到。符号连接本身只是一个路径名。而另一种思想是使用权限作为二进制名。在这种方法中,查找一个ASCII名就产生一个权限,这种权限具有多种形式。例如,它可以包含一个物理的或逻辑的机器号或者某个适当的服务器的网络地址,还可以是一个表明所需文件的数字
19、。物理地址常用于向服务器发送消息而无须作进一步的解释。逻辑地址可通过广播或通过在一个名字服务器上查找来定位。一种有时在分布式系统中出现,而在集中式系统中不会出现的最新情况是:当查找一个 ASCII名时,有可能得到多个二进制名(i-节点,权限等)。这些二进制名通常代表了原文件和它的所有备份。拥有多个二进制名,就可对其中一个文件进行定位。如果由于某种原因那个文件不可用,还可以另试一个文件。这种方法通过冗余而实现了一定程度上的容错。5.1.3 文件共享的语义当两个或更多个用户共享相同的文件时,必须精确地定义读和写的语义以避免产生问题。在允许进程共享文件的单处理机系统中,如UNIX这种语义通常规定,在
20、READ操作紧跟在WRITE操作后执行时,READ操作返回刚刚写入的值,如图5-4(a)所示。同样地,当一个READ操作跟在两个紧相连发生的WRITE操作后,读入的值就是后一个写操作写入的值。实际上,系统对所有操作都强制一个绝对时间顺序,并且总是返回最近的值。我们称这种模式为UNIX语义。这种模式易于理解且容易实现。图5-4 (a) 在单处理机中,当READ操作紧跟WRITE操作执行时,READ操作返回刚刚写入的值; (b) 在分布式系统中,可能返回已过时的值 在分布式系统中,只要仅有一个文件服务器并且客户不缓存文件, 那么UNIX语义是很容易实现的。所有READ和WRITE操作直接送到文件服
21、务器上,文件服务器严格地按顺序处理它们。这种方法表达了UNIX语义(除了由于网络延迟导致一个在写操作后仅一微秒就产生的读操作先到达服务器从而取得旧值的小问题外)。然而,实际上,如果分布式系统中所有的文件请求都必须送到某个服务器上去执行,这个系统的运行效率常常是很差的。解决这一问题的常用办法是允许客户在他们自己的高速缓存中保留经常使用的文件的局部拷贝。尽管稍后我们就要讨论文件高速缓存的具体细节,但现在也能充分地指出,如果一个客户在本地修改了一个高速缓存文件且紧接着另一个客户从这个服务器上读取这一文件,那么第二个客户就会得到一个过时的文件,如图5-4(b)所示。 解决这一问题的一个方法是立即把高速
22、缓存文件的所有修改回写到服务器上。这种方法在概念上简单,但效率很低。另一种方法是放宽文件共享的语义。为了替代一个读操作需看先前所有写操作的结果的需求,这里介绍一个新的规则:“对一个打开文件的修改仅对修改该文件的进程(也可能是机器)是初始可见的,仅当文件关闭时,其修改才对其它进程(或机器)可见。”这个规则的采用并不能改变图5-4(b)中的情形,但它确实正确地重新定义了实际的操作行为(B得到了文件的初始值)。当A关闭文件时,它把拷贝发送到服务器,这样,后面的读操作得到了所需的新值,这个规则已得到广泛应用并称之为对话语义。如果两个或者多个客户同时高速缓存和修改同一文件,使用对话语义就会发生问题。一个
23、解决办法是:当各个文件连续关闭时,将它的值送回到服务器上,这样,最后的结果取决于哪个文件最后关闭。一种稍差但更易实现的方法是最后的结果是后选者之一,但并未指明是哪一个。使用高速缓存和对话语义的一个最终困难是:除了没有让所有的读操作都返回最近回写的那个值之外,它还违背了UNIX语义的另一个方面。在UNIX中,联系每一个打开文件的是指出文件当前位置的指针。读操作从该位置开始取数据,写操作从该位置开始写数据。该指针在打开这个文件的进程和其所有子进程之间共享。使用对话语义,当其子进程在不同的机器上运行时,这种共享就无法实现。为了清楚知道抛弃共享文件指针的后果是什么,请看如下命令: RUNOUT这里,r
24、un是一个外壳程序,它执行两个程序a和b,一个跟在另一个后面。如果两个程序都产生输出,则希望在OUT中,由 b产生的输出直接跟在由a产生的输出后面。实现这种输出的方法是当b启动时,它就继承来自a的文件指针,这个文件指针是由外壳和两个进程共享的。这样b写的第一个字节就直接跟在a写的最后一个字节之后。如果使用对话语义而不用共享文件指针,那就需要一个完全不同的机制来产生外壳程序和使用共享文件指针工作的类似结构。由于没有解决这个问题的通用方法,所以每个系统都必须用特定的方式来处理它。在分布式系统中,对文件共享语义的一个完全不同的方法是使所有文件都不可变。这样,就没有办法打开一个文件来进行写操作。事实上
25、,对文件的操作仅有创建和读。创建一个全新的文件并以以前存在的一个文件名进入目录系统是可能的,但还是以前存在的那个文件就不可访问了(至少以该文件名)。这样,虽然不可能去修改文件X,还是有可能用一个新文件来自动地替代X。换句话说,虽然文件不能更新,但目录是可以更新的。一旦我们确定文件不能够被修改,有关如何处理两个进程的问题,即写文件进程和读入文件的进程,就不出现了。遗留的问题是:当两个进程试图在同一时刻去替换同一文件时,会发生什么问题。对于会话语义,最好的解决办法似乎是让其中一个新文件去替换旧文件:要么用最后一个文件,要么不确定的。更困难的问题是如果一个文件被代替而另一个进程正在忙于读它时应如何处
26、理。一种解决的办法是:以某种方式安排读进程继续使用旧文件,即使它不再处于任何目录中,类似于UNIX允许进程继续使用它所打开的文件,即使该文件已从所有的目录中删去。另一种解决的办法是检测已改变的文件并使随后对它的读操作失败。在分布式系统中,处理文件共享的第四种方法是使用原子事务处理,正如在第三章中详细讨论的那样。简而言之,为了存取一个文件或一组文件,进程首先执行某种类型的开始事务处理原语,以指示跟在其后的操作是不可分的。然后通过系统调用来读写一个或多个文件。当此工作完成后,执行结束事务处理原语。这个方法的关键特性是保证了包含于事务处理中的所有调用都将按顺序完成,而不能有其他任何同时存在的事务处理
27、的干扰。如果两个或多个事务处理同时启动,那么系统保证最后的结果和它们在某一(未规定)顺序执行时是相同的。事务处理使编程更加容易的典型的例子是在银行系统中。设想某一银行帐号有100美元,有两个进程都想往该帐号上加50美元。在非约束的系统中,每一个进程都可能同时读包含当前余额 (100)的那个文件,各自计算新的余额 (150),并成功地用这个新值写入文件。最后的结果可能是150,也可能是200,这取决于读和写时的精确计时。通过把所有这些操作组成一个事务处理,这种交错就不会出现,最后的结果总是200。方 法 描 述UNIX语义对一个文件的任何操作对所有进程都是及时可见的会话语义在文件关闭之前,对文件
28、的修改对其它进程是不可见的不可更改文件不能进行更改,只是简单的共享和复制事务所有的更改要么都完成,要么都不能完成 图5-5 在分布式系统中,处理共享文件的四种方法5.2 分布式文件系统的实现前一节,我们从用户的角度讨论了分布式文件系统的各个方面,即它们是呈现给用户的。本节将讨论文件系统是如何实现的。首先,给出文件使用的一些经验信息;然后再讨论系统结构,高速高速缓存实现,分布式系统的复制以及并发控制;最后简单地讨论一下从经验中得到的教训。5.2.1 文件的使用在实现分布式或者任何其它系统之前,对如何使用它有一个好的想法并保证最常用的操作有效是非常有用的。为此,Satyanarayanan(198
29、1)对文件使用方式进行了研究。我们将在下面给出他的主要结果。然而,首先有必要提请读者注意的是关于这些结果和类似的测量。一些测量是静态的,即这些测量只表示系统某一时刻的瞬态。静态测量是通过检查硬盘(磁盘)内容来进行的。这些测量包括:文件的大小和类型的分布,以及各种类型和大小的文件所占存储空间的总量。另外一些测量是动态的,通过对文件系统的修改,把各种操作记录到一个日志文件中以用于以后的分析。这些数据将产生关于各种操作的相对频率、任何时刻文件打开数和发生的共享数的信息。尽管静态和动态测量在根本上是不同的,但把它们结合起来使用,可以对文件系统的使用得到一个更好的描述。测量任何现存系统总会产生的一个问题
30、是要知道所观察的使用者具有怎样的典型性。Satyanarayanan的测量是在一所大学里进行的。它们可否运用于工业研究实验室?办公自动化工程?银行业务处理系统?在这些系统未装备和测量之前,没有人能确切地知道。在进行测量时,另一个固有的问题是要注意被测系统的情况(artifacts)。看一个简单的例子:当看到一个MS-DOS系统中的文件名分配时,可以迅速得到这样的结论:文件名决不会超过8个字符(加一个可选的三个字符的扩展名)。但是,由于没有人曾使用过超过8个字符的文件名,因此得到8个字符就足够了的结论可能是错误的。由于MS-DOS不允许文件名超过8个字符,所以就无法得知当用户不受这一限制时他们会
31、如何去做。最后,Satyanarayanan的测量基本是在传统的UNIX系统上进行的。这些测量能否转移到或推广到分布式系统上还不能确切知道。为此,最重要的结论列于图5-6中。根据观测资料,可得出一些结论。首先,大多数文件都小于10K,这与Mullender和Tanenbaum(1984)在不同环境下所得出的结果是一致的。这个结果表明,在服务器和客户之间传送整个文件而不是磁盘块是可行的。由于整个文件传送明显更简单且更有效,因此这个思想是值得考虑的。当然,有些文件很大,所以对它们还必须做一些规定。还有,一个好的指导方针对正常情况可以起到优化作用,而对非正常情况要特殊处理。 一个有意义的观测结果是:
32、大多数文件的生命周期都不长。一般的模式是:建立文件,读取它(也许只一次),然后删除它。编译程序就是一个典型的应用,它建立临时文件用于再运行期间传送信息。在这里暗指:在客户边建立文件并保存直到删除,可能是一个好主意。这样做可以消除客户和服务器之间大量的不必要的通信量。文件很少共享的事实为客户高速缓存提供了依据。如我们已看到的那样,高速缓存使得语义更加复杂,但如果文件很少被共享,那么最好进行客户高速缓存,并接受对话语义的结果作为更好运行效率的回报。最后,由于明显存在截然不同的文件类型,建议采用不同的机制来处理不同的文件类型。系统二进制数普遍需要,但它很难改变,所以它们也许会被广泛地复制,即使这意味着偶然的修改也是很复杂的。编译程序和其它临时文件很小,不可共享,而且消失很快,因此它们应该尽可能地保留在本地。电子邮件信箱经常被更新但极少被共享, 所以复制也无益。普通的数据文件可以共享,因此它们仍需要其它的处理。大多数文件比较小(小于10k)对文件的读操作多于对文件的写操作对文件的读写是顺序进行的,随机访问非常少大多数文件寿命比较短文件共享非常少一般进程只是使用某几个文件用不同
copyright@ 2008-2022 冰豆网网站版权所有
经营许可证编号:鄂ICP备2022015515号-1