当前位置:文档之家› 分布式文件系统学习

分布式文件系统学习

分布式文件系统学习
分布式文件系统学习

分布式基础学习
所谓分布式,在这里,很狭义的指代以 Google 的三驾马车,GFS、Map/Reduce、BigTable 为框架核心的分布 式存储和计算系统。通常如我一样初学的人,会以 Google 这几份经典的论文作为开端的。它们勾勒出了分布式存 储和计算的一个基本蓝图,已可窥见其几分风韵,但终究还是由于缺少一些实现的代码和示例,色彩有些斑驳,缺 少了点感性。幸好我们还有 Open Source,还有 Hadoop。Hadoop 是一个基于 Java 实现的,开源的,分布式 存储和计算的项目。作为这个领域最富盛名的开源项目之一,它的使用者也是大牌如云,包括了 Yahoo,Amazon, Facebook 等等(好吧,还可能有校内,不过这真的没啥分量...)。Hadoop 本身,实现的是分布式的文件系统 HDFS,和分布式的计算(Map/Reduce)框架,此外,它还不是一个人在战斗,Hadoop 包含一系列扩展项目, 包括了分布式文件数据库 HBase(对应 Google 的 BigTable),分布式协同服务 ZooKeeper(对应 Google 的 Chubby),等等。。。 如此,一个看上去不错的黄金搭档浮出水面,Google 的论文 + Hadoop 的实现,顺着论文的框架看具体的实现, 用实现来进一步理解论文的逻辑,看上去至少很美。网上有很多前辈们,做过 Hadoop 相关的源码剖析工作,我关 注最多的是这里,目前博主已经完成了 HDFS 的剖析工作,Map/Reduce 的剖析正火热进行中,更新频率之高, 剖析之详尽,都是难得一见的,所以,走过路过一定不要错过了。此外,还有很多 Hadoop 的关注者和使用者贴过 相关的文章, 比如: 这里,这里。 也可以去 Hadoop 的中文站点(不知是民间还是官方...) ,搜罗一些学习资料。 。。 我个人从上述资料中受益匪浅,而我自己要做的整理,与原始的源码剖析有些不同,不是依照实现的模块,而是基 于论文的脉络和实现这样系统的基本脉络来进行的,也算,从另一个角度给出一些东西吧。鉴于个人对于分布式系 统的理解非常的浅薄,缺少足够的实践经验,深入的问题就不班门弄斧了,仅做梳理和解析,大牛至此,可绕路而 行了。。。
一. 分布式文件系统
分布式文件系统,在整个分布式系统体系中处于最低层最基础的地位,存储嘛,没了数据,再好的计算平台,再完 善的数据库系统,都成了无水之舟了。那么,什么是分布式文件系统,顾名思义,就是分布式 文件系统 分布式+文件系统 分布式 文件系统。它包含 这两个方面的内涵,从文件系统的客户使用的角度来看,它就是一个标准的文件系统,提供了一系列 API,由此进 行文件或目录的创建、移动、删除,以及对文件的读写等操作。从内部实现来看,分布式的系统则不再和普通文件 系统一样负责管理本地磁盘, 它的文件内容和目录结构都不是存储在本地磁盘上, 而是通过网络传输到远端系统上。 并且,同一个文件存储不只是在一台机器上,而是在一簇机器上分布式存储,协同提供服务,正所谓分布式。。。 因此,考量一个分布式文件系统的实现,其实不妨可以从这两方面来分别剖析,而后合二为一。首先,看它如何去 实现文件系统所需的基本增删改查的功能。然后,看它如何考虑分布式系统的特点,提供更好的容错性,负载平衡, 等等之类的。这二者合二为一,就明白了一个分布式文件系统,整体的实现模式。。。
I. 术语对照
说任何东西,都需要统一一下语言先,不然明明说的一个意思,却容易被理解到另一个地方去。Hadoop 的分布式 文件系统 HDFS,基本是按照 Google 论文中的 GFS 的架构来实现的。但是,HDFS 为了彰显其不走寻常路的本 性,其中的大量术语,都与 GFS 截然不同。明明都是一个枝上长的土豆,它偏偏就要叫山药蛋,弄得水火不容的, 苦了我们看客。秉承老好人,谁也不得罪的方针,文中,既不采用 GFS 的叫法,也不采用 Hadoop 的称谓,而是 另辟蹊径,自立门户,搞一套自己的中文翻译,为了避免不必要的痛楚,特此先来一帖术语对照表,要不懂查一查, 包治百病。。。
文中所用翻译 主控服务器
HDFS 中的术语 NameNode
GFS 中的术语 Master
术语解释 整个文件系统的大脑,它
1

提供整个文件系统的目 录信息,并且管理各个数 据服务器。 分布式文件系统中的每 一个文件,都被切分成若 干个数据块,每一个数据 块都被存储在不同的服 务器上,此服务器称之为 数据服务器。 每个文件都会被切分成 若干个块,每一块都有连 续的一段文件内容,是存 储的基恩单位,在这里统 一称做数据块。 客户端写文件的时候,不 是一个字节一个字节写 入文件系统的,而是累计 到一定数量后,往文件系 统中写入一次,每发送一 次的数据,都称为一个数 据包。 在每一个数据包中,都会 将数据切成更小的块,每 一个块配上一个奇偶校 验码,这样的块,就是传 输块。 备用的主控服务器,在身 后默默的拉取着主控服 务器 的日志,等待主控 服务器牺牲后被扶正。
数据服务器
DataNode
Chunk Server
数据块
Block
Chunk
数据包
Packet

传输块
Chunk

备份主控服务器
SecondaryNameNode 无
*注:本文采用的 Hadoop 是 0.19.0 版本。 注
II. 基本架构
1. 服务器介绍 与单机的文件系统不同,分布式文件系统不是将这些数据放在一块磁盘上,由上层操作系统来管理。而是存放在一 个服务器集群上,由集群中的服务器,各尽其责,通力合作,提供整个文件系统的服务。其中重要的服务器包括: 主控服务器(Master/NameNode),数据服务器 数据服务器(ChunkServer/DataNode),和客户服务器 客户服务器。HDFS 和 GFS 主控服务器 数据服务器 客户服务器 都是按照这个架构模式搭建的。个人觉得,其中设计的最核心内容是:文件的目录结构独立存储在一个主控服务器 文件的目录结构独立存储在一个主控服务器 上,而具体文件数据,拆分成若干块,冗余的存放在不同的数据服务器上。 而具体文件数据,拆分成若干块, 冗余的存放在不同的数据服务器上。 存储目录结构的主控服务器,在 GFS 中称为 Master,在 HDFS 中称为 NameNode。这两个名字,叫得都有各 自的理由,是瞎子摸象各表一面。Master 是之于数据服务器来叫的,它做为数据服务器的领导同志存在,管理各 个数据服务器,收集它们的信息,了解所有数据服务器的生存现状,然后给它们分配任务,指挥它们齐心协力为系
2

统服务;而 NameNode 是针对客户端来叫的,对于客户端而言,主控服务器上放着所有的文件目录信息,要找一 个文件,必须问问它,由此而的此名。。。 主控服务器在整个集群中,同时提供服务的只存在一个,如果它不幸牺牲的话,会有后备军立刻前赴后继的跟上, 但,同一时刻,需要保持一山不容二虎的态势。这种设计策略,避免了多台服务器间即时同步数据的代价,而同时, 它也使得主控服务器很可能成为整个架构的瓶颈所在。因此,尽量为主控服务器减负,不然它做太多的事情,就自 因此,尽量为主控服务器减负,不然它做太多的事情, 因此 然而然的晋升成了一个分布式文件系统的设计要求。。。 然而然的晋升成了一个分布式文件系统的设计要求 每一个文件的具体数据,被切分成若干个数据块,冗余的存放在数据服务器。通常的配置,每一个数据块的大小为 64M,在三个数据服务器上冗余存放(这个 64M,不是随便得来的,而是经过反复实践得到的。因为如果太大, 容易造成热点的堆叠,大量的操作集中在一台数据服务器上,而如果太小的话,附加的控制信息传输成本,又太高 了。因此没有比较特定的业务需求,可以考虑维持此配置...)。数据服务器是典型的四肢发达头脑简单的苦力,其 其 主要的工作模式就是定期向主控服务器汇报其状况,然后等待并处理命令,更快更安全的存放好数据 主要的工作模式就是定期向主控服务器汇报其状况,然后等待并处理命令,更快更安全的存放好数据。。。 此外,整个分布式文件系统还有一个重要角色是客户端 客户端。它不和主控服务和数据服务一样,在一个独立的进程中提 客户端 供服务,它只是以一个类库(包)的模式存在,为用户提供了文件读写、目录操作等 APIs。当用户需要使用分布 它只是以一个类库( 它只是以一个类库 的模式存在,为用户提供了文件读写、 式文件系统进行文件读写的时候, 把客户端相关包给配置上, 就可以通过它来享受分布式文件系统提供的服务了。 。 。 2. 数据分布 一个文件系统中,最重要的数据,其实就是整个文件系统的目录结构和具体每个文件的数据。具体的文件数据被切 分成数据块,存放在数据服务器上。每一个文件数据块,在数据服务器上都表征为出双入队的一对文件(这是普通 的 Linux 文件),一个是数据文件,一个是附加信息的元文件,在这里,不妨把这对文件简称为数据块文件 数据块文件。数据 数据块文件 块文件存放在数据目录 数据目录下,它有一个名为 current 的根目录,然后里面有若干个数据块文件和从 dir0-dir63 的最 数据目录 多 64 个的子目录,子目录内部结构等同于 current 目录,依次类推(更详细的描述,参见这里)。个人觉得,这 样的架构,有利于控制同一目录下文件的数量,加快检索速度。。。 这是磁盘上的物理结构, 与之对应的, 是内存中的数据结构, 用以表征这样的磁盘结构, 方便读写操作的进行。 Block 类用于表示数据块,而 FSDataset 类是数据服务器管理文件块的数据结构,其中,FSDataset.FSDir 对应着数 据块文件和目录,FSDataset.FSVolume 对应着一个数据目录,FSDataset.FSVolumeSet 是 FSVolume 的集合,每一个 FSDataset 有一个 FSVolumeSet。多个数据目录,可以放在不同的磁盘上,这样有利于加快磁 盘操作的速度。相关的类图,可以参看这里 。。。 此外,与 FSVolume 对应的,还有一个数据结构,就是 DataStorage,它是 Storage 的子类,提供了升级、 回滚等支持。但与 FSVolume 不一样,它不需要了解数据块文件的具体内容,它只知道有这么一堆文件放这里,会 有不同版本的升级需求, 它会处理怎么把它们升级回滚之类的业务 (关于 Storage, 可以参见这里) 而 FSVolume 。 提供的接口,都基本上是和 Block 相关的。。。 相比数据服务器,主控服务器的数据量不大,但逻辑更为复杂。主控服务器主要有三类数据:文件系统的目录结构 文件系统的目录结构 数据,各个文件的分块信息 数据块的位置信息 数据 各个文件的分块信息,数据块的位置信息 各个文件的分块信息 数据块的位置信息(就数据块放置在哪些数据服务器上...)。在 GFS 和 HDFS 的架 构中, 只有文件的目录结构和分块信息才会被持久化到本地磁盘 持久化到本地磁盘上, 而数据块的位置信息则是通过动态汇总过来的, 持久化到本地磁盘 仅仅存活在内存数据结构中,机器挂了,就灰飞烟灭了。每一个数据服务器启动后,都会向主控服务器发送注册消 仅仅存活在内存数据结构中 息,将其上数据块的状况都告知于主控服务器。俗话说,简单就是美,根据 DRY 原则,保存的冗余信息越少,出 现不一致的可能性越低, 付出一点点时间的代价, 换取了一大把逻辑上的简单性, 绝对应该是一个包赚不赔的买卖。 。 。 在 HDFS 中,FSNamespacesystem 类就负责保管文件系统的目录结构以及每个文件的分块状况的,其中,前 者是由 FSDirectory 类来负责,后者是各个 INodeFile 本身维护。在 INodeFile 里面,有一个 BlockInfo 的 数组,保存着与该文件相关的所有数据块信息,BlockInfo 中包含了从数据块到数据服务器的映射,INodeFile 只 需要知道一个偏移量,就可以提供相关的数据块,和数据块存放的数据服务器信息。。。 3、服务器间协议 、 在 Hadoop 的实现中,部署了一套 RPC 机制,以此来实现各服务间的通信协议。在 Hadoop 中,每一对服务器间 的通信协议,都定义成为一个接口 接口。服务端的类实现该接口,并且建立 RPC 服务,监听相关的接口,在独立的线程 接口
3

处理 RPC 请求。客户端则可以实例化一个该接口的代理对象,调用该接口的相应方法,执行一次同步 同步的通信,传入 同步 相应参数,接收相应的返回值。基于此 RPC 的通信模式,是一个消息拉取 消息拉取的流程,RPC 服务器等待 RPC 客户端的 消息拉取 调用,而不会先发制人主动把相关信息推送到 RPC 客户端去。。。 其实 RPC 的模式和原理,实在是没啥好说的,之所以说,是因为可以通过把握好这个,彻底理顺 Hadoop 各服务 器间的通信模式。Hadoop 会定义一些列的 RPC 接口,只需要看谁实现,谁调用,就可以知道谁和谁通信,都做些 啥事情,图中服务器的基本架构、各服务所使用的协议、调用方向、以及协议中的基本内容。。。
III. 基本的文件操作
4

基本的文件操作,可以分成两类,一个是对文件目录结构的操作,比如文件和目录的创建、删除、移动、更名等等; 另一个是对文件数据流的操作,包括读取和写入文件数据。当然,文件读和写,是有本质区别的,尤其是在数据冗 余的情况下,因此,当成两类操作也不足为过。此外,要具体到读写的类别,也是可以再继续分类下去的。在 GFS 的论文中,对于分布式文件系统的读写场景有一个重要的假定(其实是从实际业务角度得来的...):就是文件的读 取是由大数据量的连续读取和小数据量的随机读取组成,文件的写入则基本上都是批量的追加写,和偶尔的插入写 (GFS 中还有大量的假设, 它们构成了分布式文件系统架构设计的基石。 每一个系统架构都是搭建在一定假设上的, 这些假设有些来自于实际业务的状况,有些是因为天生的条件约束,不基于假设理解设计,肯定会有失偏颇...)。 在 GFS 中,对文件的写入分成追加写和插入写都有所支持,但是,在 HDFS 中仅仅支持追加写,这大大降低了复 杂性。关于 HDFS 与 GFS 的一些不同,可以参看这里。。。 1. 文件和目录的操作 文件目录的信息,全部囤积在主控服务器上,因此,所有对文件目录的操作,只会直接涉及到客户端和主控服务器。 整个目录相关的操作流程基本都是这样的:客户端 DFSClient 调用 ClientProtocol 定义的相关函数,该操作通 过 RPC 传送到其实现者主控服务器 NameNode 那里,NameNode 做相关的处理后(很少...),调用 FSNamesystem 的相关函数。在 FSNamesystem 中,往往是做一些验证和租约操作,具体的目录结构操作交 由 FSDirectory 的相应函数来操作。最后,依次返回,经由 RPC 传送回客户端。具体各操作涉及到的函数和具 体步骤,参见下表:
相关操作
ClientProtocol FSNamesystem FSDirectory / NameNode
关键步骤 1. 检查是否有写权限; 2. 检查是否已经存在此文件, 如 果是覆写,则先进行删除操作; 3. 在指定路径下添加 INodeFileUnderConstruction 的文件实例; 4. 写日志; 5. 签订租约。 1. 检查指定目录是否是目录; 2. 检查是否有相关权限; 3. 在指定路径的 INode 下,添 加子节点; 4. 写日志。 1. 检查相关路径的权限; 2. 从老路径下移除, 在新路径下 添加; 3. 修改相关父路径的修改时间; 4. 写日志; 5. 将租约从老路径移动到新路 径下。 1. 如果不是递归删除, 确认指定 路径是否是空目录; 2. 检查相关权限; 3. 在目录结构上移除相关
5
创建文件
create
startFile
addFile
创建目录
mkdirs
mkdirs
mkdirs
改名操作
rename
renameTo
renameTo
删除操作
delete
delete
delete

INode; 4. 修改父路径的修改时间; 5. 将相关的数据块, 放入到废弃 队列中去,等待处理; 6. 写日志; 7. 废弃相关路径的租约。 1. 检查 owner 判断是否有操作 权限; setPermission 2. 修改指定路径下 INode 的权 限; 3. 写日志。 1. 检查是否有操作权限; 2. 修改指定路径下 INode 的权 限; 3. 写日志。 1. 检查是否有写权限; 2. 修改指定路径 INode 的时间 信息; 3. 写日志。
设置权限
setPermission
setPermission
设置用户
setOwner
setOwner
setOwner
设置时间
setTimes
setTimes
setTimes
从上表可以看到,其实有的操作本质上还是涉及到了数据服务器,比如文件创建和删除操作。但是,之前提到,主 控服务器只于数据服务器是一个等待拉取的地位,它们不会主动联系数据服务器,将指令传输给它们,而是放到相 应的数据结构中,等待数据服务器来取。这样的设计,可以减少通信的次数,加快操作的执行速度。。。 另,上述步骤中,有些日志和租约相关的操作,从概念上来说,和目录操作其实没有任何联系,但是,为了满足分 布式系统的需求,这些操作是非常有必要的,在此,按下不表。。。 2、文件的读取 、 不论是文件读取,还是文件的写入,主控服务器扮演的都是中介 中介的角色。客户端把自己的需求提交给主控服务器, 中介 主控服务器挑选合适的数据服务器,介绍给客户端,让客户端和数据服务器单聊,要读要写随你们便。这种策略类 似于 DMA,降低了主控服务器的负载,提高了效率。。。 因此,在文件读写操作中,最主要的通信,发生在客户端与数据服务器之间。它们之间跑的协议是 ClientDatanodeProtocol。从这个协议中间,你无法看到和读写相关的接口,因为,在 Hadoop 中,读写操 读写操 机制的,而是另立门户,独立搭了一套通信框架。在数据服务器一端,DataNode 类中有一个 作是不走 RPC 机制的 DataXceiverServer 类的实例,它在一个单独的线程等待请求,一旦接到,就启动一个 DataXceiver 的线程, 处理此次请求。一个请求一个线程,对于数据服务器来说,逻辑上很简单。当下,DataXceiver 支持的请求类型有 六种,具体的请求包和回复包格式,请参见这里,这里,这里。在 Hadoop 的实现中,并没有用类来封装这些请求, 而是按流的次序写下来, 这给代码阅读带来挺多的麻烦, 也对代码的维护带来一定的困难, 不知道是出于何种考虑。 。 。 相比于写, 文件的读取实在是一个简单的过程。 在客户端 DFSClient 中, 有一个 DFSClient.DFSInputStream 类。当需要读取一个文件的时候,会生成一个 DFSInputStream 的实例。它会先调用 ClientProtocol 定义 getBlockLocations 接口,提供给 NameNode 文件路径 读取位置 读取长度 文件路径、读取位置 读取长度信息,从中取得一个 读取位置、读取长度 LocatedBlocks 类的对象, 这个对象包含一组 LocatedBlock, 那里面有所规定位置中包含的所有数据块信息, 以及数据块对应的所有数据服务器的位置信息。当读取开始后,DFSInputStream 会先尝试从某个数据块对应的 一组数据服务器中选出一个,进行连接。这个选取算法,在当下的实现中,非常简单,就是选出第一个未挂的数据 选出第一个未挂的数据 服务器,并没有加入客户端与数据服务器相对位置的考量。读取的请求,发送到数据服务器后,自然会有 服务器
6

DataXceiver 来处理, 数据被一个包一个包发送回客户端, 等到整个数据块的数据都被读取完了, 就会断开此链接, 尝试连接下一个数据块对应的数据服务器,整个流程,依次如此反复,直到所有想读的都读取完了为止。。。 尝试连接下一个数据块对应的数据服务器 3、文件的写入 、 文件读取是一个一对一的过程,一个客户端,只需要与一个数据服务器联系,就可以获得所需的内容。但是,写入 操作,则是一个一对多的流程。一次写入,需要在所有存放相关数据块的数据服务器都保持同步的更新,有任何的 差池,整个流程就告失败。。。 在分布式系统中,一旦涉及到写入操作,并发处理难免都会沦落成为一个变了相的串行操作。因为,如果不同的客 户端如果是任意时序并发写入的话,整个写入的次序无法保证,可能你写半条记录我写半条记录,最后出来的结果 乱七八糟不可估量。在 HDFS 中,并发写入的次序控制,是由主控服务器来把握的。当创建、续写一个文件的时候, 该文件的节点类,由 INodeFile 升级成为 INodeFileUnderConstruction,INodeFileUnderConstruction 是 INodeFile 的子类,它起到一个锁的作用。如果当一个客户端想创建或续写的文件是 INodeFileUnderConstruction,会引发异常,因为这说明这个此处有爷,请另寻高就,从而保持了并发写入的次 序性。同时,INodeFileUnderConstruction 有包含了此时正在操作它的客户端的信息以及最后一个数据块的数据 服务器信息,当追加写的时候可以更快速的响应。。。 与读取类似,DFSClient 也有一个 DFSClient.DFSOutputStream 类,写入开始,会创建此类的实例。 DFSOutputStream 会从 NameNode 上拿一个 LocatedBlock,这里面有最后一个数据块的所有数据服务器的 信息。这些数据服务器每一个 每一个都需要能够正常工作(对于读取,只要还有一个能工作的就可以实现...),它们会依 每一个 照客户端的位置被排列成一个有着最近物理距离和最小的序列 排列成一个有着最近物理距离和最小的序列(物理距离,是根据机器的位置定下来的...),这个 排列成一个有着最近物理距离和最小的序列 排序问题类似于著名旅行商问题,属于 NP 复杂度,但是由于服务器数量不多,所以用最粗暴的算法,也并不会看 上去不美。。。 文件写入,就是在这一组数据服务器上构造成数据流的双向流水线 双向流水线。DFSOutputStream,会与序列的第一个数据 双向流水线 服务器建立 Socket 连接,发送请求头,然后等待回应。DataNode 同样是建立 DataXceiver 来处理写消息, DataXceiver 会依照包中传过来的其他服务器的信息,建立与下一个服务器的连接,并生成类似的头,发送给它, 并等待回包。此流程依次延续,直到最后一级,它发送回包,反向着逐级传递,再次回到客户端。如果一切顺利, 那么此时,流水线建立成功,开始正式发送数据。数据是分成一个个数据包发送的,所有写入的内容,被缓存在客 户端, 当写满 64K, 会被封装成 DFSOutputStream.Packet 类实例, 放入 DFSOutputStream 的 dataQueue 队列。 DFSOutputStream.DataStreamer 会时刻监听这个队列, 一旦不为空, 则开始发送, 将位于 dataQueue 队首的包移动到 ackQueue 队列的队尾, 表示已发送但尚未接受回复的包队列。 同时启动 ResponseProcessor 线程监听回包, 直到收到相应回包, 才将发送包从 ackQueue 中移除, 表示成功。 每一个数据服务器的 DataXceiver 收到了数据包, 一边写入到本地文件中去, 一边转发给下一级的数据服务器, 等待回包, 同前面建立流水线的流程。 。 。 当一个数据块写满了之后,客户端需要向主控服务器申请追加新的数据块。这个会引起一次数据块的分配,成功后, 会将新的数据服务器组返还给客户端。然后重新回到上述流程,继续前行。。。 关于写入的流程,还可以参见这里。此外,写入涉及到租约问题,后续会仔细的来说。。。
IV. 分布式支持
如果单机的文件系统是田里勤恳的放牛娃,那么分布式文件系统就是刀尖上讨饭吃的马贼了。在分布式环境中,有 太多的意外,数据随时传输错误,服务器时刻准备牺牲,很多平常称为异常的现象,在这里都需要按照平常事来对 待。因此,对于分布式文件系统而言,仅仅是满足了正常状况下文件系统各项服务还不够,还需要保证分布式各种 意外场景下健康持续的服务,否则,将一无是处。。。 1、服务器的错误恢复 、
7

在分布式环境中,哪台服务器牺牲都是常见的事情,牺牲不可怕,可怕的是你都没有时刻准备好它们会牺牲。作为 一个合格的分布式系统,HDFS 当然时刻准备好了前赴后继奋勇向前。HDFS 有三类服务器,每一类服务器出错了, 都有相应的应急策略。。。
a. 客户端
生命最轻如鸿毛的童鞋,应该就是客户端了。毕竟,做为一个文件系统的使用者,在整个文件系统中的地位,难免 有些归于三流。而作为客户端,大部分时候,牺牲了就牺牲了,没人哀悼,无人同情,只有在在辛勤写入的时候, 不幸辞世(机器挂了,或者网络断了,诸如此类...),才会引起些恐慌。因为,此时此刻,在主控服务器上对应的 文件, 正作为 INodeFileUnderConstruction 活着, 仅仅为占有它的那个客户端服务者, 做为一个专一的文件, 它不允许别的客户端染指。这样的话,一旦占有它的客户端服务者牺牲了,此客户端会依然占着茅坑不拉屎,让如 花似玉 INodeFileUnderConstruction 孤孤单单守寡终身。这种事情当然无法容忍,因此,必须有办法解决这个 问题,办法就是:租约 租约。。。 租约 租约,顾名思义,就是当客户端需要占用某文件的时候,与主控服务器签订的一个短期合同。这个合同有一个期限, 当客户端需要占用某文件的时候,与主控服务器签订的一个短期合同 当客户端需要占用某文件的时候 在这个期限内,客户端可以延长合同期限,一旦超过期限,主控服务器会强行终止此租约,将这个文件的享用权, 分配给他人。。。 在打开或创建一个文件,准备追加写之前,会调用 LeaseManager 的 addLease 方法,在指定的路径下与此客 户端签订一份租约。客户端会启动 DFSClient.LeaseChecker 线程,定时轮询调用 ClientProtocol 的 renewLease 方法,续签租约。在主控服务器一端,有一个 LeaseManager.Monitor 线程,始终在轮询检查 所有租约,查看是否有到期未续的租约。如果一切正常,该客户端完成写操作,会关闭文件,停止租约,一旦有所 意外,比如文件被删除了,客户端牺牲了,主控服务器都会剥夺此租约,如此,来避免由于客户端停机带来的资源 被长期霸占的问题。。。
b. 数据服务器
当然,会挂的不只是客户端,海量的数据服务器是一个更不稳定的因素。一旦某数据服务器牺牲了,并且主控服务 器被蒙在鼓中,主控服务器就会变相的欺骗客户端,给它们无法连接的读写服务器列表,导致它们处处碰壁无法工 作。因此,为了整个系统的稳定,数据服务器必须时刻向主控服务器汇报,保持主控服务器对其的完全了解,这个 机制,就是心跳消息。在 HDFS 中,主控服务器 NameNode 实现了 DatanodeProtocol 接口,数据服务器 DataNode 会在主循环中,不停的调用该协议中的 sendHeartbeat 方法,向 NameNode 汇报状况。在此调用 中,DataNode 会将其整体运行状况告知 NameNode,比如:有多少可用空间、用了多大的空间,等等之类。 NameNode 会记住此 DataNode 的运行状况,作为新的数据块分配或是负载均衡的依据。当 NameNode 处理完 成此消息后,会将相关的指令封装成一个 DatanodeCommand 对象,交还给 DataNode,告诉数据服务器什 么数据块要删除什么数据块要新增等等之类,数据服务器以此为自己的行动依据。。。 但是,sendHeartbeat 并没有提供本地的数据块信息给 NameNode,那么主控服务器就无法知道此数据服务器应 该分配什么数据块应该删除什么数据块,那么它是如何决定的呢?答案就是 DatanodeProtocol 定义的另一个方 法,blockReport。DataNode 也是在主循环中定时调用此方法,只是,其周期通常比调用 sendHeartbeat 的 更长。它会提交本地的所有数据块状况给 NameNode,NameNode 会和本地保存的数据块信息比较,决定什么该 删除什么该新增,并将相关结果缓存在本地对应的数据结构中,等待此服务器再发送 sendHeartbeat 消息过来的 时候,依照这些数据结构中的内容,做出相应的 DatanodeCommand 指令。blockReport 方法同样也会返回一 个 DatanodeCommand 给 DataNode,但通常,只是为空(只有出错的时候不为空),我想,增加缓存,也许 是为了确保每个指令都可以重复发送并确定被执行。。。
c. 主控服务器
当然,作为整个系统的核心和单点,含辛茹苦的主控服务器含泪西去,整个分布式文件服务集群将彻底瘫痪罢工。 如何在主控服务器牺牲后,提拔新的主控服务器并迅速使其进入工作角色,就成了系统必须考虑的问题。解决策略 就是:日志 日志。。。 日志 其实这并不是啥新鲜东西,一看就知道是从数据库那儿偷师而来的。在主控服务器上,所有对文件目录操作的关键 步骤(具体文件内容所处的数据服务器,是不会被写入日志的,因为这些内容是动态建立的...),都会被写入日志。 另外,主控服务器会在某些时刻,将当下的文件目录完整的序列化到本地,这称为镜像 镜像。一旦存有镜像,镜像前期 镜像 所写的日志和其他镜像,都纯属冗余,其历史使命已经完成,可以报废删除了。在主控服务器不幸牺牲,或者是战
8

略性的停机修整结束,并重新启动后,主控服务器会根据最近的镜像 + 镜像之后的所有日志 最近的镜像 镜像之后的所有日志,重建整个文件目录, 迅速将服务能力恢复到牺牲前的水准。。。 对于数据服务器而言,它们会通过一些手段,迅速得知顶头上司的更迭消息。它们会立刻转投新东家的名下,在新 东家旗下注册,并开始向其发送心跳消息,这个机制,可能用分布式协同服务来实现,这里不说也罢。。。 在 HDFS 的实现中,FSEditLog 类是整个日志体系的核心,提供了一大堆方便的日志写入 API,以及日志的恢复 存储等功能。目前,它支持若干种日志类型,都冠以 OP_XXX,并提供相关 API,具体可以参见这里。为了保证日 志的安全性,FSEditLog 提供了 EditLogFileOutputStream 类作为写入的承载类,它会同时开若干个本地文 件,然后依次写入,防止日志的损坏导致不可估量的后果。在 FSEditLog 上面,有一个 FSImage 类,存储文件 镜像并调用 FSEditLog 对外提供相关的日志功能。FSImage 是 Storage 类的子类,如果对数据块的讲述有所印 象的话,你可以回忆起来,凡事从此类派生出来的东西,都具有版本性质,可以进行升级和回滚等等,以此,来实 现产生镜像是对原有日志和镜像处理的复杂逻辑。。。 目前,在 HDFS 的日志系统中,有些地方与 GFS 的描述有所不同。在 HDFS 中,所有日志文件和镜像文件都是本 地文件,这就相当于,把日志放在自家的保险箱中,一旦主控服务器挂了,别的后继而上的服务器也无法拿到这些 日志和镜像,用于重振雄风。因此,在 HDFS 中,运行着一个 SecondaryNameNode 服务器,它做为主控服 务器的替补,隐忍厚积薄发为篡位做好准备,其中,核心内容就是:定期下载并处理日志和镜像 定期下载并处理日志和镜像。 定期下载并处理日志和镜像 SecondaryNameNode 看上去像客户端一样,与 NameNode 之间,走着 NamenodeProtocol 协议。它会不 停的查看主控服务器上面累计日志的大小,当达到阈值后,调用 doCheckpoint 函数,此函数的主要步骤包括: ? ? ? ? ? ? ? 首先是调用 startCheckpoint 做一些本地的初始化工作; 然后调用 rollEditLog,将 NameNode 上此时操作的日志文件从 edit 切到 edit.new 上来,这个操作 瞬间完成,上层写日志的函数完全感觉不到差别; 接着,调用 downloadCheckpointFiles,将主控服务器上的镜像文件和日志文件都下载到此候补主控 服务器上来; 并调用 doMerge,打开镜像和日志,将日志生成新的镜像,保存覆盖; 下一步,调用 putFSImage 把新的镜像上传回 NameNode; 再调用 rollFsImage,将镜像换成新的,在日志从 edit.new 改名为 edit; 最后,调用 endCheckpoint 做收尾工作。
整个算法涉及到 NameNode 和 SecondaryNameNode 两个服务器,最终结果是 NameNode 和 SecondaryNameNode 都依照算法进行前 算法进行前的日志生成了镜像。而两个服务器上日志文件的内容,前者是整个算法 算法进行前 算法 进行期间所写的日志,后者始终不会有任何日志。当主控服务器牺牲的时候,运行 SecondaryNameNode 的服务 进行期间 器立刻被扶正,在其上启动主控服务,利用其日志和镜像,恢复文件目录,并逐步接受各数据服务器的注册,最终 向外提供稳定的文件服务。。。 同样的事情,GFS 采用的可能是另外一个策略,就是在写日志的时候,并不局限在本地,而是同时书写网络日志 网络日志, 网络日志 即在若干个远程服务器上生成同样的日志。然后,在某些时机,主控服务器自己,生成镜像,降低日志规模。当主 控服务器牺牲,可以在拥有网络日志的服务器上启动主控服务,升级成为主控服务器。。。 GFS 与 HDFS 的策略相比较, 前者是化整为零, 后者则是批量处理, 通常我们认为, 批量处理的平均效率更高一些, 且相对而言,可能实现起来容易一些,但是,由于有间歇期,会导致日志的丢失,从而无法 100%的将备份主控服 务器的状态与主控服务器完全同步。。。 2、数据的正确性保证 、 在复杂纷繁的分布式环境中,我们坚定的相信,万事皆有可能。哪怕各个服务器都舒舒服服的活着,也可能有各种 各样的情况导致网络传输中的数据丢失或者错误。并且在分布式文件系统中,同一份文件的数据,是存在大量冗余 备份的,系统必须要维护所有的数据块内容完全同步,否则,一人一言,不同客户端读同一个文件读出不同数据, 用户非得疯了不可。。。 在 HDFS 中,为了保证数据的正确性和同一份数据的一致性,做了大量的工作。首先,每一个数据块,都有一个版 本标识,在 Block 类中,用一个长整型的数 generationStamp 来表示版本信息(Block 类是所有表示数据块 的数据结构的基类),一旦数据块上的数据有所变化,此版本号将向前增加 向前增加。在主控服务器上,保存有此时每个数 向前增加
9

据块的版本,一旦出现数据服务器上相关数据块版本与其不一致,将会触发相关的恢复流程。这样的机制保证了各 个数据服务器器上的数据块,在基本大方向上都是一致的。但是,由于网络的复杂性,简单的版本信息无法保证具 体内容的一致性(因为此版本信息与内容无关,可能会出现版本相同,但内容不同的状况)。因此,为了保证数据 内容上的一致,必须要依照内容,作出签名 签名。。。 签名 当客户端向数据服务器追加写入数据包时,每一个数据包的数据,都会切分成 512 字节 字节大小的段,作为签名验证 的基本单位, HDFS 中, 在 把这个数据段称为 Chunk, (注意, GFS 中, 在 Chunk 表达的是数据块...) 。 , 即传输块 在每一个数据包中,都包含若干个传输块以及每一个传输块的签名,当下,这个签名是根据 Java SDK 提供的 CRC 算法算得的,其实就是一个奇偶校验。当数据包传输到流水线的最后一级 最后一级,数据服务器会对其进行验证(想一想, 最后一级 为什么只在最后一级做验证,而不是每级都做...),一旦发现当前的传输块签名与在客户端中的签名不一致,整个 数据包的写入被视为无效,Lease Recover(租约恢复)算法被触发。。。 (租约恢复) 从基本原理上看,这个算法很简单,就是取所有数据服务器上此数据块的最小长度当作正确内容的长度,将其他数 取所有数据服务器上此数据块的最小长度当作正确内容的长度, 取所有数据服务器上此数据块的最小长度当作正确内容的长度 据服务器上此数据块超出此长度的部分切除。从正确性上看,此算法无疑是正确的,因为至少有一个数据服务器会 据服务器上此数据块超出此长度的部分切除 发现此错误,并拒绝写入,那么,如果写入了的,都是正确的;从效率上看,此算法也是高效的,因为它避免了重 复的传输和复杂的验证,仅仅是各自删除尾部的一些内容即可。但从具体实现上来看,此算法稍微有些绕,因为, 为了降低本已不堪重负的主控服务器的负担,此算法不是由主控服务器这个大脑发起的,而是通过选举一个数据服 务器作为 Primary,由 Primary 发起,通过调用与其他各数据服务器间的 InterDatanodeProtocol 协议,最 终完成的。具体的算法流程,参见 LeaseManager 类上面的注释。需要说明的是此算法的触发时机和发起者。 此算法可以由客户端 客户端或者是主控服务器 主控服务器发起,当客户端在写入一个数据包失败后,会发起租约恢复。因为,一次写 客户端 主控服务器 入失败,不论是何种原因,很有可能就会导致流水线上有的服务器写了,有的没写,从而造成不统一。而主控服务 器发起的时机,则是在占有租约的客户端超出一定时限没有续签,这说明客户端可能挂了,在临死前可能干过不利 于数据块统一的事情,作为监督者,主控服务器需要发起一场恢复运动,确保一切正确。。。 3、负载均衡 、 负载的均衡,是分布式系统中一个永恒的话题,要让大家各尽其力齐心干活,发挥各自独特的优势,不能忙得忙死 闲得闲死,影响战斗力。而且,负载均衡也是一个复杂的问题,什么是均衡,是一个很模糊的概念。比如,在分布 式文件系统中,总共三百个数据块,平均分配到十个数据服务器上,就算均衡了么?其实不一定,因为每一个数据 块需要若干个备份,各个备份的分布应该充分考虑到机架的位置,同一个机架的服务器间通信速度更快,而分布在 不同机架则更具有安全性,不会在一棵树上吊死。。。 在这里说的负载均衡,是宽泛意义上的均衡过程,主要涵盖两个阶段的事务,一个是在任务初始分配的时候尽可能 合理分配,另一个是在事后时刻监督及时调整。。。 在 HDFS 中,ReplicationTargetChooser 类,是负责实现为新分配的数据块寻找婆家的。基本上来说,数据 块的分配工作和备份的数量、申请的客户端地址(也就是写入者)、已注册的数据服务器位置,密切相关。其算法 基本思路是只考量静态位置信息,优先照顾写入者的速度,让多份备份分配到不同的机架去。具体算法,自行参见 源码。此外,HDFS 的 Balancer 类,是为了实现动态的负载调整而存在的。Balancer 类派生于 Tool 类,这说 明, 它是以一个独立的进程存在的, 可以独立的运行和配置。 它运行有 NamenodeProtocol 和 ClientProtocol 两个协议,与主控服务器进行通信,获取各个数据服务器的负载状况,从而进行调整。主要的调整其实就是一个操 作,将一个数据块从一个服务器搬迁到另一个服务器上。Balancer 会向相关的目标数据服务器 目标数据服务器发出一个 目标数据服务器 DataTransferProtocol.OP_REPLACE_BLOCK 消息, 接收到这个消息的数据服务器, 会将数据块写入本地, 成功后,通知主控服务器,删除早先的那个数据服务器上的同一块数据块。具体的算法请自行参考源码。。。 4、垃圾回收 、 对于垃圾,大家应该耳熟能详了,在分布式文件系统而言,没有利用价值的数据块备份,就是垃圾。在现实生活中, 我们提倡垃圾分类,为了更好的理解分布式文件系统的垃圾收集,搞个分类也是很有必要的。基本上,所有的垃圾 都可以视为两类,一类是由系统正常逻辑产生 系统正常逻辑产生的,比如某个文件被删除了,所有相关的数据块都沦为垃圾了,某个 系统正常逻辑产生 数据块被负载均衡器移动了,原始数据块也不幸成了垃圾了。此类垃圾最大的特点,就是主控服务器是生成垃圾的 主控服务器是生成垃圾的
10

罪魁祸首,也就是说主控服务器完全了解有哪些垃圾需要处理。另外还有一类垃圾,是由于系统的一些异常症状产 系统的一些异常症状产 罪魁祸首 生的,比如某个数据服务器停机了一段,重启之后发现其上的某个数据块已经在其他服务器上重新增加了此数据块 的备份,它上面的那个备份过期了失去价值了,需要被当作垃圾来处理了。此类垃圾的特点恰恰相反,主控服务器 主控服务器 无法直接了解到垃圾状况,需要曲线救国。。。 无法直接了解到垃圾状况 在 HDFS 中,第一类垃圾的判定自然很容易,在一些正常的逻辑中产生的垃圾,全部被塞进了 FSNamesystem 的 recentInvalidateSets 这个 Map 中。而第二类垃圾的判定,则放在数据服务器发送其数据块信息来的过程 中,经过与本地信息的比较,可以断定,此数据服务器上有哪些数据块已经不幸沦为垃圾。同样,这些垃圾也被塞 到 recentInvalidateSets 中去。在与数据服务器进行心跳交流的过程中,主控服务器会将它上面有哪些数据块需 要删除,数据服务器对这些数据块的态度是,直接物理删除 直接物理删除。在 GFS 的论文中,对如何删除一个数据块有着不同的 直接物理删除 理解,它觉着应该先缓存起来,过几天没人想恢复它了再删除。在 HDFS 的文档中,则明确表示,在现行的应用场 景中,没有需要这个需求的地方,因此,直接删除就完了。这说明,理念是一切分歧的根本:)。。。
V. 总结
整个分布式文件系统,计算系统,数据库系统的设计理念,基本是一脉相承的。三类服务器、作为单点存在的核心 控制服务器、基于日志的恢复机制、基于租约的保持联系机制、等等,在后续分布式计算系统和分布式数据库中都 可以看到类似的影子,在分布式文件系统这里,我详述了这些内容,可能在后续就会默认知道而说的比较简略了。 而刨去这一些,分布式文件系统中最大特点,就是文件块的冗余存储,它直接导致了较为复杂的写入流程。当然, 虽说分布式文件系统在分布式计算和数据库中都有用到,但如果对其机理没有兴趣,只要把它当成是一个可以在任 在任 何机器上使用的文件系统,就不会对其他上层建筑的理解产生障碍。。。 何机器上使用
分布式计算( 二. 分布式计算(Map/Reduce) )
分布式式计算,同样是一个宽泛的概念,在这里,它狭义的指代,按 Google Map/Reduce 框架所设计的分布式框 架。在 Hadoop 中,分布式文件系统,很大程度上,是为各种分布式计算需求所服务的。我们说分布式文件系统就 是加了分布式的文件系统,类似的定义推广到分布式计算上,我们可以将其视为增加了分布式支持的计算函数 增加了分布式支持的计算函数。从 增加了分布式支持的计算函数 计算的角度上看,Map/Reduce 框架接受各种格式的键值对文件作为输入,读取计算后,最终生成自定义格式的输 出文件。而从分布式的角度上看,分布式计算的输入文件往往规模巨大,且分布在多个机器上,单机计算完全不可 支撑且效率低下,因此 Map/Reduce 框架需要提供一套机制,将此计算扩展到无限规模的机器集群上进行。依照 这样的定义,我们对整个 Map/Reduce 的理解,也可以分别沿着这两个流程去看。。。 在 Map/Reduce 框架中,每一次计算请求, 被称为作业 在分布式计算 Map/Reduce 框架中, 作业。 为了完成这个作业, 作业 它进行两步走的战略,首先是将其拆分成若干个 Map 任务 任务,分配到不同的机器上去执行,每一个 Map 任务拿输入 文件的一部分作为自己的输入,经过一些计算,生成某种格式的中间文件,这种格式,与最终所需的文件格式完全 一致,但是仅仅包含一部分数据。因此,等到所有 Map 任务完成后,它会进入下一个步骤,用以合并这些中间文 件获得最后的输出文件。此时,系统会生成若干个 Reduce 任务 任务,同样也是分配到不同的机器去执行,它的目标, 就是将若干个 Map 任务生成的中间文件为汇总到最后的输出文件中去。当然,这个汇总不总会像 1 + 1 = 2 那么
11

直接了当,这也就是 Reduce 任务的价值所在。经过如上步骤,最终,作业完成,所需的目标文件生成。整个算法 的关键,就在于增加了一个中间文件生成的流程,大大提高了灵活性,使其分布式扩展性得到了保证。。。
I. 术语对照
和分布式文件系统一样, Google、 Hadoop 和....我, 各执一种方式表述统一概念, 为了保证其统一性, 特有下表。 。 。
文中翻译 作业 Job
Hadoop 术语 Job
Google 术语
相关解释 用户的每一个计算请求, 就称为一个作业。 用户提交作业的服务器, 同时,它还负责各个作业 任务的分配,管理所有的 任务服务器。 任劳任怨的工蜂,负责执 行具体的任务。 每一个作业,都需要拆分 开了,交由多个服务器来 完成,拆分出来的执行单 位,就称为任务。 每一个任务,都有可能执 行失败或者缓慢,为了降 低为此付出的代价,系统 会未雨绸缪的实现在另 外的任务服务器上执行 同样一个任务,这就是备 份任务。
作业服务器
JobTracker
Master
任务服务器
TaskTracker
Worker
任务
Task
Task
备份任务
Speculative Task
Buckup Task
II. 基本架构
与分布式文件系统类似,Map/Reduce 的集群,也由三类服务器构成。其中作业服务器 作业服务器,在 Hadoop 中称为 Job 作业服务器 Tracker,在 Google 论文中称为 Master。前者告诉我们,作业服务器是负责管理运行在此框架下所有作业的, 后者告诉我们,它也是为各个作业分配任务的核心。与 HDFS 的主控服务器类似,它也是作为单点存在的,简化了 负责的同步流程。具体的负责执行用户定义操作 负责执行用户定义操作的,是任务服务器 任务服务器,每一个作业被拆分成很多的任务 任务,包括 Map 负责执行用户定义操作 任务服务器 任务 任务和 Reduce 任务等,任务是具体执行的基本单元,它们都需要分配到合适任务服务器上去执行,任务服务器 任务 任务 一边执行一边向作业服务器汇报各个任务的状态,以此来帮助作业服务器了解作业执行的整体情况,分配新的任务 等等。。。
12

除了作业的管理者执行者,还需要有一个任务的提交者 任务的提交者,这就是客户端。与分布式文件系统一样,客户端也不是一 任务的提交者 个单独的进程,而是一组 API,用户需要自定义好自己需要的内容,经由客户端相关的代码,将作业及其相关内容 和配置,提交到作业服务器去,并时刻监控执行的状况。。。 同作为 Hadoop 的实现,与 HDFS 的通信机制相同,Hadoop Map/Reduce 也是用了协议接口来进行服务器间的 交流。实现者作为 RPC 服务器,调用者经由 RPC 的代理进行调用,如此,完成大部分的通信,具体服务器的架构, 和其中运行的各个协议状况,参见下图。从图中可以看到,与 HDFS 相比,相关的协议少了几个,客户端与任务服 务器,任务服务器之间,都不再有直接通信关系。这并不意味着客户端就不需要了解具体任务的执行状况,也不意 味着,任务服务器之间不需要了解别家任务执行的情形,只不过,由于整个集群各机器的联系比 HDFS 复杂的多, 直接通信过于的难以维系,所以,都统一由作业服务器整理转发。另外,从这幅图可以看到,任务服务器不是一个 人在战斗,它会像孙悟空一样招出一群宝宝帮助其具体执行任务。这样做的好处,个人觉得,应该有安全性方面的 考虑,毕竟,任务的代码是用户提交的,数据也是用户指定的,这质量自然良莠不齐,万一碰上个搞破坏的,把整 个任务服务器进程搞死了,就因小失大了。因此,放在单独的地盘进行,爱咋咋地,也算是权责明确了。。。
与分布式文件系统相比,Map/Reduce 框架的还有一个特点,就是可定制性强 可定制性强。文件系统中很多的算法,都是很固 可定制性强 定和直观的,不会由于所存储的内容不同而有太多的变化。而作为通用的计算框架,需要面对的问题则要复杂很多, 在各种不同的问题、 不同的输入、 不同的需求之间, 很难有一种包治百病的药能够一招鲜吃遍天。 作为 Map/Reduce
13

框架而言,一方面要尽可能的抽取出公共的一些需求,实现出来。更重要的,是需要提供良好的可扩展机制,满足 用户自定义各种算法的需求。Hadoop 是由 Java 来实现的,因此通过反射来实现自定义的扩展,显得比较小菜一 碟了。在 JobConf 类中,定义了大量的接口,这基本上是 Hadoop Map/Reduce 框架所有可定制内容的一次集 中展示。在 JobConf 中,有大量 set 接口接受一个 Class的参数,通常它都有一个默认实现 的类,用户如果不满意,则可自定义实现。。。
III. 计算流程
如果一切都按部就班的进行, 那么整个作业的计算流程, 应该是作业的提交 -> Map 任务的分配和执行 -> Reduce 任务的分配和执行 -> 作业的完成。而在每个任务的执行中,又包含输入的准备 -> 算法的执行 -> 输出的生成, 三个子步骤。沿着这个流程,我们可以很快的整理清晰整个 Map/Reduce 框架下作业的执行。。。
1、作业的提交 、
一个作业,在提交之前,需要把所有应该配置的东西都配置好,因为一旦提交到了作业服务器上,就陷入了完全自 动化的流程,用户除了观望,最多也就能起一个监督作用,惩治一些不好好工作的任务。。。 基本上,用户在提交代码阶段,需要做的工作主要是这样的: 首先,书写好所有自定的代码,最起码,需要有 Map 和 Reduce 的执行代码。在 Hadoop 中,Map 需要派生自 Mapper接口,Reduce 需要派生自 Reducer接口。这里都是用的泛 型,用以支持不同的键值类型。这两个接口都仅有一个方法,一个是 map,一个是 reduce,这两个方法都直接受 四个参数,前两个是输入的键和值相关的数据结构,第三个是作为输出 键 值 输出相关的数据结构,最后一个,是一个 输出 Reporter 类的实例,实现的时候可以利用它来统计一些计数。除了这两个接口,还有大量可以派生的接口,比如 分割的 Partitioner接口。。。 然后, 需要书写好主函数的代码, 其中最主要的内容就是实例化一个 JobConf 类的对象, 然后调用其丰富的 setXXX 接口,设定好所需的内容,包括输入输出的文件路径,Map 和 Reduce 的类,甚至包括读取写入文件所需的格式支 持类,等等。。。 最后,调用 JobClient 的 runJob 方法,提交此 JobConf 对象。runJob 方法会先行调用到 JobSubmissionProtocol 接口所定义的 submitJob 方法,将此作业,提交给作业服务器。接着,runJob 开 始循环,不停的调用 JobSubmissionProtocol 的 getTaskCompletionEvents 方法,获得 TaskCompletionEvent 类的对象实例,了解此作业各任务的执行状况。。。
2、Map 任务的分配 、
14

当一个作业提交到了作业服务器上,作业服务器会生成若干个 Map 任务,每一个 Map 任务,负责将一部分的输入 转换成格式与最终格式相同的中间文件。 通常一个作业的输入都是基于分布式文件系统的文件 作业的输入都是基于分布式文件系统的文件 (当然在单机环境下, 作业的输 文件系统单机的也可以...),因为,它可以很天然的和分布式的计算产生联系。而对于一个 Map 任务而言,它的 输入往往是输入文件的一个数据块,或者是数据块的一部分,但通常,不跨数据块 不跨数据块。因为,一旦跨了数据块,就可 不跨数据块 能涉及到多个服务器,带来了不必要的复杂性。。。 当一个作业,从客户端提交到了作业服务器上,作业服务器会生成一个 JobInProgress 对象,作为与之对应的 标识,用于管理。作业被拆分成若干个 Map 任务后,会预先挂在作业服务器上的任务服务器拓扑树。这是依照分 布式文件数据块的位置来划分的,比如一个 Map 任务需要用某个数据块,这个数据块有三份备份,那么,在这三 台服务器上都会挂上此任务,可以视为是一个预分配。。。 关于任务管理和分配的大部分的真实功能和逻辑的实现,JobInProgress 则依托 JobInProgressListener 和 TaskScheduler 的子类。TaskScheduler,顾名思义是用于任务分配的策略类(为了简化描述,用它代指所有 TaskScheduler 的子类...)。它会掌握好所有作业的任务信息,其 assignTasks 函数,接受一个 TaskTrackerStatus 作为参数,依照此任务服务器的状态和现有的任务状况,为其分配新的任务。而为了掌握 所有作业相关任务的状况,TaskScheduler 会将若干个 JobInProgressListener 注册到 JobTracker 中去,当 有新的作业到达、移除或更新的时候,JobTracker 会告知给所有的 JobInProgressListener,以便它们做出相应 的处理。。。 任务分配是一个重要的环节,所谓任务分配,就是将合适作业的合适任务分配到合适的服务器上 将合适作业的合适任务分配到合适的服务器上。不难看出,里面 将合适作业的合适任务分配到合适的服务器上 蕴含了两个步骤,先是选择作业,然后是在此作业中选择任务。和所有分配工作一样,任务分配也是一个复杂的活。 不良好的任务分配,可能会导致网络流量增加、某些任务服务器负载过重效率下降,等等。不仅如此,任务分配还 是一个无一致模式的问题,不同的业务背景,可能需要不同的算法才能满足需求。因此,在 Hadoop 中,有很多 TaskScheduler 的子类,像 Facebook,Yahoo,都为其贡献出了自家用的算法。在 Hadoop 中,默认的任务分 配器,是 JobQueueTaskScheduler 类。它选择作业的基本次序是:Map Clean Up Task(Map 任务服务器 的清理任务,用于清理相关的过期的文件和环境...) -> Map Setup Task(Map 任务服务器的安装任务,负责配 置好相关的环境...) -> Map Tasks -> Reduce Clean Up Task -> Reduce Setup Task -> Reduce Tasks。 在这个前提下,具体到 Map 任务的分配上来。当一个任务服务器工作的游刃有余,期待获得新的任务的时候, JobQueueTaskScheduler 会按照各个作业的优先级,从最高优先级的作业 最高优先级的作业开始分配。每分配一个,还会为其留出 最高优先级的作业 余量,已被不时之需。举一个例子:系统目前有优先级 3、2、1 的三个作业,每个作业都有一个可分配的 Map 任 务,一个任务服务器来申请新的任务,它还有能力承载 3 个任务的执行,JobQueueTaskScheduler 会先从优先 级 3 的作业上取一个任务分配给它,然后再留出一个 1 任务的余量。此时,系统只能在将优先级 2 作业的任务分配 给此服务器,而不能分配优先级 1 的任务。这样的策略,基本思路就是一切为高优先级的作业服务 一切为高优先级的作业服务,优先分配不说, 一切为高优先级的作业服务
15

分配了好保留有余力以备不时之需,如此优待,足以让高优先级的作业喜极而泣,让低优先级的作业感慨既生瑜何 生亮,甚至是活活饿死。。。 确定了从哪个作业提取任务后,具体的分配算法,经过一系列的调用,最后实际是由 JobInProgress 的 findNewMapTask 函数完成的。它的算法很简单,就是尽全力为此服务器非配且尽可能好的分配任务 尽全力为此服务器非配且尽可能好的分配任务,也就是 尽全力为此服务器非配且尽可能好的分配任务 说,只要还有可分配的任务,就一定会分给它,而不考虑后来者。作业服务器会从离它最近的服务器开始,看上面 是否还挂着未分配的任务(预分配上的),从近到远,如果所有的任务都分配了,那么看有没有开启多次执行,如 果开启,考虑把未完成的任务再分配一次(后面有地方详述...)。。。 对于作业服务器来说,把一个任务分配出去了,并不意味着它就彻底解放,可以对此任务可以不管不顾了。因为任 务可以在任务服务器上执行失败,可能执行缓慢,这都需要作业服务器帮助它们再来一次。因此在 Task 中,记录 有一个 TaskAttemptID,对于任务服务器而言,它们每次跑的,其实都只是一个 Attempt 而已,Reduce 任务 只需要采信一个的输出,其他都算白忙乎了。。。
3、Map 任务的执行 、
与 HDFS 类似,任务服务器是通过心跳消息,向作业服务器汇报此时此刻其上各个任务执行的状况,并向作业服务 器申请新的任务的。具体实现,是 TaskTracker 调用 InterTrackerProtocol 协议的 heartbeat 方法来做 的。这个方法接受一个 TaskTrackerStatus 对象作为参数,它描述了此时此任务服务器的状态。当其有余力接 受新的任务的时候, 它还会传入 acceptNewTasks 为 true 的参数, 表示希望作业服务器委以重任。 JobTracker 接收到相关的参数后,经过处理,会返回一个 HeartbeatResponse 对象。这个对象中,定义了一组 TaskTrackerAction,用于指导任务服务器进行下一步的工作。系统中已定义的了一堆其 TaskTrackerAction 的 子类,有的对携带的参数进行了扩充,有的只是标明了下 ID,具体不详写了,一看便知。。。 当 TaskTracker 收到的 TaskTrackerAction 中,包含了 LaunchTaskAction,它会开始执行所分配的新的任 务。在 TaskTracker 中,有一个 TaskTracker.TaskLauncher 线程(确切的说是两个,一个等 Map 任务, 一个等 Reduce 任务),它们在痴痴的守候着新任务的来到。一旦等到了, 会最终调用到 Task 的 createRunner 方法,构造出一个 TaskRunner 对象,新建一个线程来执行。对于一个 Map 任务,它对应的 Runner 是 TaskRunner 的子类 MapTaskRunner,不过,核心部分都在 TaskRunner 的实现内。TaskRunner 会先将所 需的文件全部下载并拆包好,并记录到一个全局缓存中,这是一个全局的目录,可以供所有此作业的所有任务使用。 它会用一些软链接,将一些文件名链接到这个缓存中来。然后,根据不同的参数,配置出一个 JVM 执行的环境,这 个环境与 JvmEnv 类的对象对应。 接着,TaskRunner 会调用 JvmManager 的 launchJvm 方法,提交给 JvmManager 处理。JvmManager 用于管理该 TaskTracker 上所有运行的 Task 子进程。 在目前的实现中, 尝试的是池化的方式。 有若干个固定的槽, 如果槽没有满,那么就启动新的子进程,否则,就寻找 idle 的进程,如果是同 Job 的直接放进去,否则杀死这个进
16

程,用一个新的进程代替。每一个进程都是由 JvmRunner 来管理的,它也是位于单独线程中的。但是从实现上看, 这个机制好像没有部署开,子进程是死循环等待,而不会阻塞在父进程的相关线程上,父线程的变量一直都没有个 调整,一旦分配,始终都处在繁忙的状况了。 真实的执行载体,是 Child,它包含一个 main 函数,进程执行,会将相关参数传进来,它会拆解这些参数,并且 构造出相关的 Task 实例,调用其 run 函数进行执行。每一个子进程,可以执行指定个数量的 Task,这就是上面 所说的池化的配置。但是,这套机制在我看来,并没有运行起来,每个进程其实都没有机会不死而执行新的任务, 只是傻傻的等待进程池满,而被一刀毙命。也许是我老眼昏花,没看出其中实现的端倪。。。
4、Reduce 任务的分配与执行 、
比之 Map 任务,Reduce 的分配及其简单,基本上是所有 Map 任务完成了,有空闲的任务服务器,来了就给分配 一个 Job 任务。因为 Map 任务的结果星罗棋布,且变化多端,真要搞一个全局优化的算法,绝对是得不偿失。而 Reduce 任务的执行进程的构造和分配流程,与 Map 基本完全的一致,没有啥可说的了。。。 但其实, Reduce 任务与 Map 任务的最大不同, Map 任务的文件都在本地隔着, Reduce 任务需要到处采集。 是 而 这个流程是作业服务器经由此 Reduce 任务所处的任务服务器, 告诉 Reduce 任务正在执行的进程, 它需要的 Map 任务执行过的服务器地址,此 Reduce 任务服务器会于原 Map 任务服务器联系(当然本地就免了...),通过 FTP 服务,下载过来。这个隐含的直接数据联系,就是执行 Reduce 任务与执行 Map 任务最大的不同了。。。
17

5、作业的完成 、
18

当所有 Reduce 任务都完成了,所需数据都写到了分布式文件系统上,整个作业才正式完成了。此中,涉及到很多 的类,很多的文件,很多的服务器,所以说起来很费劲,话说,一图解千语,说了那么多,我还是画两幅图,彻底 表达一下吧。。。 首先,是一个时序图。它模拟了一个由 3 个 Map 任务和 1 个 Reduce 任务构成的作业执行流程。我们可以看到, 在执行的过程中,只要有人太慢,或者失败,就会增加一次尝试,以此换取最快的执行总时间。一旦所有 Map 任 务完成,Reduce 开始运作(其实,不一定要这样的...),对于每一个 Map 任务来说,只有执行到 Reduce 任务 把它上面的数据下载完成,才算成功,否则,都是失败,需要重新进行尝试。。。
而第二副图,不是我画的,就不转载了,参见这里,它描述了整个 Map/Reduce 的服务器状况图,包括整体流程、 所处服务器进程、输入输出等,看清楚这幅图,对 Map/Reduce 的基本流程应该能完全跑通了。有这几点,可能 图中描述的不够清晰需要提及一下,一个是在 HDFS 中,其实还有日志文件,图中没有标明;另一个是步骤 5,其 实是由 TaskTracker 主动去拉取而不是 JobTracker 推送过来的;还有步骤 8 和步骤 11,创建出来的 MapTask 和 ReduceTask,在 Hadoop 中都是运行在独立的进程上的。。。
IV. Map 任务详请 任务详请
从上面,可以了解到整个 Map 和 Reduce 任务的整体流程,而后面要啰嗦的,是具体执行中的细节。Map 任务的 输入,是分布式文件系统上的,包含键值对信息的文件。为了给每一个 Map 任务指定输入,我们需要掌握文件格 式把它分切成块,并从每一块中分离出键值信息。在 HDFS 中,输入的文件格式,是由 InputFormat 类来表示的,在 JobConf 中,它的默认值是 TextInputFormat 类(见 getInputFormat),此类是特化的 FileInputFormat子类,而 FileInputFormat正是 InputFormat的子类。 通过这样的关系我们可以很容易的理解, 默认的文件格式是文本文件 且键是 LongWritable 类型 文本文件, (整 文本文件 形数),值是 Text 类型(字符串)。仅仅知道文件类型是不够的,我们还需要将文件中的每一条数据,分离成键 值对,这个工作,是 RecordReader来做的。在 TextInputFormat 的 getRecordReader 方法中我 们可以看到,与 TextInputFormat 默认配套使用的,是 LineRecordReader 类,是特化的 RecordReader的子类,它将每一行作为一个记录,起始的位置作为键,整行的字符 一行作为一个记录, 一行作为一个记录 起始的位置作为键, 串作为值。有了格式,分出了键值,还需要切开分给每一个 Map 任务。每一个 Map 任务的输入用 InputSplit 接 串作为值 口表示,对于一个文件输入而言,其实现是 FileSplit,它包含着文件名、起始位置、长度和存储它的一组服务器 文件名、 文件名 起始位置、 地址。。。 地址 当 Map 任务拿到所属的 InputSplit 后,就开始一条条读取记录,并调用用于定义的 Mapper,进行计算(参见 MapRunner和 MapTask 的 run 方法),然后,输出。MapTask 会传递给 Mapper 一个 OutputCollector对象, 作为输出的数据结构。 它定义了一个 collect 的函数, 接受一个键值对。 MapTask 在
19

中,定义了两个 OutputCollector 的子类,一个是 MapTask.DirectMapOutputCollector,人如其名, 它的实现确实很 Direct,直截了当。它会利用一个 RecordWriter对象,collect 一调用,就直接调用 RecordWriter的 write 方法,写入本地的文件中去。如果觉着 RecordWriter出现的很突兀,那 么看看上一段提到的 RecordReader,基本上,数据结构都是对应着的,一个是输入一个是输出。输出很 对称也是由 RecordWriter和 OutputFormat来协同完成的, 其默认实现是 LineRecordWriter和 TextOutputFormat,多么的眼熟啊。。。 除了这个非常直接的实现之外,MapTask 中还有一个复杂的多的实现,是 MapTask.MapOutputBuffer。有道是简单压倒一切,那为什么有很简单的实现,要琢磨一个复杂的呢。 原因在于,看上去很美的往往带着刺,简单的输出实现,每调用一次 collect 就写一次文件,频繁的硬盘操作很有 可能导致此方案的低效。为了解决这个问题,这就有了这个复杂版本,它先开好一段内存做缓存 缓存,然后制定一个比 缓存 例做阈值 开一个线程监控 阈值,开一个线程监控 阈值 开一个线程监控此缓存。collect 来的内容,先写到缓存中,当监控线程发现缓存的内容比例超过阈值, 挂起所有写入操作, 建一个新的文件 把缓存的内容批量刷到此文件中 新的文件, 刷到此文件中去, 清空缓存, 重新开放, 接受继续 collect。 。 。 新的文件 刷到此文件中 为什么说是刷到文件中去呢。因为这不是一个简单的照本宣科简单复制的过程,在写入之前,会先将缓存中的内存, 经过排序、合并器(Combiner)统计之后,才会写入。如果你觉得 Combiner 这个名词听着太陌生,那么考虑一 下 Reducer,Combiner 也就是一个 Reducer 类,通过 JobConf 的 setCombinerClass 进行设置,在常用的配 置中,Combiner 往往就是用用户为 Reduce 任务定义的那个 Reducer 子类。只不过,Combiner 只是服务的范 围更小一些而已, 它在 Map 任务执行的服务器本地, 依照 Map 处理过的那一小部分数据, 先做一次 Reduce 操作, 这样,可以压缩需要传输内容的大小,提高速度。每一次刷缓存,都会开一个新的文件,等此任务所有的输入都处 理完成后,就有了若干个有序的、经过合并的输出文件。系统会将这些文件搞在一起,再做一个多路的归并外排, 同时使用合并器进行合并,最终,得到了唯一的、有序的、经过合并的中间文件(注:文件数量等同于分类数量, 在不考虑分类的时候,简单的视为一个...)。它,就是 Reduce 任务梦寐以求的输入文件。。。 除了做合并,复杂版本的 OutputCollector,还具有分类 分类的功能。分类,是通过 Partitioner来定义 分类 的,默认实现是 HashPartitioner,作业提交者可以通过 JobConf 的 setPartitionerClass 来自 , 定义。分类的含义是什么呢,简单的说,就是将 Map 任务的输出,划分到若干个文件中(通常与 Reduce 任务数 目相等),使得每一个 Reduce 任务,可以处理某一类文件。这样的好处是大大的,举一个例子说明一下。比如有 一个作业是进行单词统计 单词统计的,其 Map 任务的中间结果应该是以单词为键,以单词数量为值的文件。如果这时候只 以单词为键,以单词数量为值的文件 单词统计 以单词为键 有一个 Reduce 任务,那还好说,从全部的 Map 任务 任务那里收集文件过来,分别统计得到最后的输出文件就好。但 全部的 是,如果单 Reduce 任务无法承载此负载或效率太低,就需要多个 Reduce 任务并行执行。此时,再沿用之前的模 式就有了问题。每个 Reduce 任务从一部分 Map 任务 任务那里获得输入文件,但最终的输出结果并不正确,因为同一 一部分 个单词可能在不同的 Reduce 任务那里都有统计,需要想方法把它们统计在一起才能获得最后结果,这样就没有将 Map/Reduce 的作用完全发挥出来。这时候,就需要用到分类。如果此时有两个 Reduce 任务,那么将输出分成
20

分布式文件系统MFS(moosefs)实现存储共享

由于用户数量的不断攀升,我对访问量大的应用实现了可扩展、高可靠的集群部署(即lvs+keepalived的方式),但仍然有用户反馈访问慢的问题。通过排查个服务器的情况,发现问题的根源在于共享存储服务器NFS。在我这个网络环境里,N个服务器通过nfs方式共享一个服务器的存储空间,使得 NFS服务器不堪重负。察看系统日志,全是nfs服务超时之类的报错。一般情况下,当nfs客户端数目较小的时候,NFS性能不会出现问题;一旦NFS服务器数目过多,并且是那种读写都比较频繁的操作,所得到的结果就不是我们所期待的。 下面是某个集群使用nfs共享的示意图: 这种架构除了性能问题而外,还存在单点故障,一旦这个NFS服务器发生故障,所有靠共享提供数据的应用就不再可用,尽管用rsync方式同步数据到另外一个服务器上做nfs服务的备份,但这对提高整个系统的性能毫无帮助。基于这样一种需求,我们需要对nfs服务器进行优化或采取别的解决方案,然而优化并不能对应对日益增多的客户端的性能要求,因此唯一的选择只能是采取别的解决方案了;通过调研,分布式文件系统是一个比较合适的选择。采用分布式文件系统后,服务器之间的数据访问不再是一对多的关系(1个NFS服务器,多个NFS 客户端),而是多对多的关系,这样一来,性能大幅提升毫无问题。 到目前为止,有数十种以上的分布式文件系统解决方案可供选择,如 lustre,hadoop,Pnfs等等。我尝试了 PVFS,hadoop,moosefs这三种应用,参看了lustre、KFS等诸多技术实施方法,最后我选择了moosefs(以下简称MFS)

这种分布式文件系统来作为我的共享存储服务器。为什么要选它呢?我来说说我的一些看法: 1、实施起来简单。MFS的安装、部署、配置相对于其他几种工具来说,要简单和容易得多。看看lustre 700多页的pdf文档,让人头昏吧。 2、不停服务扩容。MFS框架做好后,随时增加服务器扩充容量;扩充和减少容量皆不会影响现有的服务。注:hadoop也实现了这个功能。 3、恢复服务容易。除了MFS本身具备高可用特性外,手动恢复服务也是非常快捷的,原因参照第1条。 4、我在实验过程中得到作者的帮助,这让我很是感激。 MFS文件系统的组成 1、元数据服务器。在整个体系中负责管理管理文件系统,目前MFS只支持一个元数据服务器master,这是一个单点故障,需要一个性能稳定的服务器来充当。希望今后MFS能支持多个master服务器,进一步提高系统的可靠性。 2、数据存储服务器chunkserver。真正存储用户数据的服务器。存储文件时,首先把文件分成块,然后这些块在数据服务器chunkserver之间复制(复制份数可以手工指定,建议设置副本数为3)。数据服务器可以是多个,并且数量越多,可使用的“磁盘空间”越大,可靠性也越高。 3、客户端。使用MFS文件系统来存储和访问的主机称为MFS的客户端,成功挂接MFS文件系统以后,就可以像以前使用NFS一样共享这个虚拟性的存储了。 元数据服务器安装和配置

分布式文件系统设计方案

分布式文件系统(DFS)解决方案 一“分布式文件系统(DFS)”概述 DFS并不是一种文件系统,它是Windows Server System上的一种客户/服务器模式的网络服务。它可以让把局域网中不同计算机上的不同的文件共享按照其功能组织成一个逻辑的分级目录结构。系统管理员可以利用分布式文件系统(DFS),使用户访问和管理那些物理上跨网络分布的文件更加容易。通过DFS,可以使分布在多个服务器或者不同网络位置的文件在用户面前显示时,就如同位于网络上的一个位置。用户在访问文件时不再需要知道和指定它们的实际物理位置。 例如,如果您的销售资料分散在某个域中的多个存储设备上,您可以利用DFS 使其显示时就好像所有的资料都位于同一网络共享下,这样用户就不必到网络上的多个位置去查找他们需要的信息。 二部署使用“分布式文件系统(DFS)”的原因 ●访问共享文件夹的用户分布在一个站点的多个位置或多个站点上; ●大多数用户都需要访问多个共享文件夹; ●通过重新分布共享文件夹可以改善服务器的负载平衡状况; ●用户需要对共享文件夹的不间断访问;

●您的组织中有供内部或外部使用的Web 站点; ●用户访问共享文件需要权限。 三“分布式文件系统(DFS)”类型 可以按下面两种方式中的任何一种来实施分布式文件系统: 1.作为独立的分布式文件系统。 ●不使用Active Directory。 ●至多只能有一个根目录级别的目标。 ●使用文件复制服务不能支持自动文件复制。 ●通过服务器群集支持容错。 2.作为基于域的分布式文件系统。 ●必须宿主在域成员服务器上。 ●使它的DFS 名称空间自动发布到Active Directory 中。 ●可以有多个根目录级别的目标。 ●通过FRS 支持自动文件复制。 ●通过FRS 支持容错。 四分布式文件系统特性 除了Windows Server System 中基于服务器的DFS 组件外,还有基于客户的DFS 组件。DFS 客户程序可以将对DFS 根目录或DFS 链接的引用缓存一段时间,该时间由管理员指定。此存储和读取过程对于

分布式文件存储方案

1DFS系统 (DFS) 是AFS的一个版本,作为开放软件基金会(OSF)的分布 分布式文件系统 式计算环境(DCE)中的文件系统部分。 如果文件的访问仅限于一个用户,那么分布式文件系统就很容易实现。可惜的是,在许多网络环境中这种限制是不现实的,必须采取并发控制来实现文件的多用户访问,表现为如下几个形式: 只读共享任何客户机只能访问文件,而不能修改它,这实现起来很简单。 受控写操作采用这种方法,可有多个用户打开一个文件,但只有一个用户进行写修改。而该用户所作的修改并不一定出现在其它已打开此文件的用户的屏幕上。 并发写操作这种方法允许多个用户同时读写一个文件。但这需要操作系统作大量的监控工作以防止文件重写,并保证用户能够看到最新信息。这种方法即使实现得很好,许多环境中的处理要求和网络通信量也可能使它变得不可接受。 NFS和AFS的区别 NFS和AFS的区别在于对并发写操作的处理方法上。当一个客户机向服务器请求一个文件(或数据库记录),文件被放在客户工作站的高速缓存中,若另一个用户也请求同一文件,则它也会被放入那个客户工作站的高速缓存中。当两个客户都对文件进行修改时,从技术上而言就存在着该文件的三个版本(每个客户机一个,再加上服务器上的一个)。有两种方法可以在这些版本之间保持同步: 无状态系统在这个系统中,服务器并不保存其客户机正在缓存的文件的信息。因此,客户机必须协同服务器定期检查是否有其他客户改变了自己正在缓存的文件。这种方法在大的环境中会产生额外的LAN通信开销,但对小型LAN来说,这是一种令人满意的方法。NFS 就是个无状态系统。 回呼(Callback)系统在这种方法中,服务器记录它的那些客户机的所作所为,并保留它们正在缓存的文件信息。服务器在一个客户机改变了一个文件时使用一种叫回叫应答(callbackpromise)的技术通知其它客户机。这种方法减少了大量网络通信。AFS(及OSFDCE的DFS)就是回叫系统。客户机改变文件时,持有这些文件拷贝的其它客户机就被回叫并通知这些改变。 无状态操作在运行性能上有其长处,但AFS通过保证不会被回叫应答充斥也达到了这一点。方法是在一定时间后取消回叫。客户机检查回叫应答中的时间期限以保证回叫应答是当前有效的。回叫应答的另一个有趣的特征是向用户保证了文件的当前有效性。换句话说,若

Hadoop分布式文件系统:架构和设计

Hadoop分布式文件系统:架构和设计 引言 (2) 一前提和设计目标 (2) 1 hadoop和云计算的关系 (2) 2 流式数据访问 (2) 3 大规模数据集 (2) 4 简单的一致性模型 (3) 5 异构软硬件平台间的可移植性 (3) 6 硬件错误 (3) 二HDFS重要名词解释 (3) 1 Namenode (4) 2 secondary Namenode (5) 3 Datanode (6) 4 jobTracker (6) 5 TaskTracker (6) 三HDFS数据存储 (7) 1 HDFS数据存储特点 (7) 2 心跳机制 (7) 3 副本存放 (7) 4 副本选择 (7) 5 安全模式 (8) 四HDFS数据健壮性 (8) 1 磁盘数据错误,心跳检测和重新复制 (8) 2 集群均衡 (8) 3 数据完整性 (8) 4 元数据磁盘错误 (8) 5 快照 (9)

引言 云计算(cloud computing),由位于网络上的一组服务器把其计算、存储、数据等资源以服务的形式提供给请求者以完成信息处理任务的方法和过程。在此过程中被服务者只是提供需求并获取服务结果,对于需求被服务的过程并不知情。同时服务者以最优利用的方式动态地把资源分配给众多的服务请求者,以求达到最大效益。 Hadoop分布式文件系统(HDFS)被设计成适合运行在通用硬件(commodity hardware)上的分布式文件系统。它和现有的分布式文件系统有很多共同点。但同时,它和其他的分布式文件系统的区别也是很明显的。HDFS是一个高度容错性的系统,适合部署在廉价的机器上。HDFS 能提供高吞吐量的数据访问,非常适合大规模数据集上的应用。 一前提和设计目标 1 hadoop和云计算的关系 云计算由位于网络上的一组服务器把其计算、存储、数据等资源以服务的形式提供给请求者以完成信息处理任务的方法和过程。针对海量文本数据处理,为实现快速文本处理响应,缩短海量数据为辅助决策提供服务的时间,基于Hadoop云计算平台,建立HDFS分布式文件系统存储海量文本数据集,通过文本词频利用MapReduce原理建立分布式索引,以分布式数据库HBase 存储关键词索引,并提供实时检索,实现对海量文本数据的分布式并行处理.实验结果表 明,Hadoop框架为大规模数据的分布式并行处理提供了很好的解决方案。 2 流式数据访问 运行在HDFS上的应用和普通的应用不同,需要流式访问它们的数据集。HDFS的设计中更多的考虑到了数据批处理,而不是用户交互处理。比之数据访问的低延迟问题,更关键的在于数据访问的高吞吐量。 3 大规模数据集 运行在HDFS上的应用具有很大的数据集。HDFS上的一个典型文件大小一般都在G字节至T字节。因此,HDFS被调节以支持大文件存储。它应该能提供整体上高的数据传输带宽,能在一个集群里扩展到数百个节点。一个单一的HDFS实例应该能支撑数以千万计的文件。

分布式文件系统Hadoop HDFS与传统文件系统Linux FS的比较与分析

6苏州大学学报(工科版)第30卷 图1I-IDFS架构 2HDFS与LinuxFS比较 HDFS的节点不管是DataNode还是NameNode都运行在Linux上,HDFS的每次读/写操作都要通过LinuxFS的读/写操作来完成,从这个角度来看,LinuxPS是HDFS的底层文件系统。 2.1目录树(DirectoryTree) 两种文件系统都选择“树”来组织文件,我们称之为目录树。文件存储在“树叶”,其余的节点都是目录。但两者细节结构存在区别,如图2与图3所示。 一二 Root \ 图2ItDFS目录树围3LinuxFS目录树 2.2数据块(Block) Block是LinuxFS读/写操作的最小单元,大小相等。典型的LinuxFSBlock大小为4MB,Block与DataN-ode之间的对应关系是固定的、天然存在的,不需要系统定义。 HDFS读/写操作的最小单元也称为Block,大小可以由用户定义,默认值是64MB。Block与DataNode的对应关系是动态的,需要系统进行描述、管理。整个集群来看,每个Block存在至少三个内容一样的备份,且一定存放在不同的计算机上。 2.3索引节点(INode) LinuxFS中的每个文件及目录都由一个INode代表,INode中定义一组外存上的Block。 HDPS中INode是目录树的单元,HDFS的目录树正是在INode的集合之上生成的。INode分为两类,一类INode代表文件,指向一组Block,没有子INode,是目录树的叶节点;另一类INode代表目录,没有Block,指向一组子INode,作为索引节点。在Hadoop0.16.0之前,只有一类INode,每个INode都指向Block和子IN-ode,比现有的INode占用更多的内存空间。 2.4目录项(Dentry) Dentry是LinuxFS的核心数据结构,通过指向父Den姆和子Dentry生成目录树,同时也记录了文件名并 指向INode,事实上是建立了<FileName,INode>,目录树中同一个INode可以有多个这样的映射,这正是连

HDFS分布式文件系统具备的优点

HDFS分布式文件系统具备的优点 随着互联网数据规模的不断增大,对文件存储系统提出了更高的要求,需要更大的容量、更好的性能以及更高安全性的文件存储系统,与传统分布式文件系统一样,HDFS分布式文件系统也是通过计算机网络与节点相连,但也有优于传统分布式文件系统的优点。 1. 支持超大文件 HDFS分布式文件系统具有很大的数据集,可以存储TB或PB级别的超大数据文件,能够提供比较高的数据传输带宽与数据访问吞吐量,相应的,HDFS开放了一些POSIX的必须接口,容许流式访问文件系统的数据。 2. 高容错性能 HDFS面向的是成百上千的服务器集群,每台服务器上存储着文件系统的部分数据,在集群的环境中,硬件故障是常见的问题,这就意味着总是有一部分硬件因各种原因而无法工作,因此,错误检测和快速、自动的恢复是HDFS最核心的架构目标,因此,HDFS具有高度的容错性。 3. 高数据吞吐量 HDFS采用的是“一次性写,多次读”这种简单的数据一致性模型,在HDFS 中,一个文件一旦经过创建、写入、关闭后,一般就不需要修改了,这样简单的一致性模型,有利于提高吞吐量。 4. 流式数据访问 HDFS的数据处理规模比较大,应用一次需要访问大量的数据,同时这些应用一般都是批量处理,而不是用户交互式处理,应用程序能以流的形式访问数据

集。 Hadoop已经迅速成长为首选的、适用于非结构化数据的大数据分析解决方案,HDFS分布式文件系统是Hadoop的核心组件之一,保证了大数据的可靠存储,与MapReduce配合使用,可以对结构化和复杂大数据进行快速、可靠分析,从而为企业做出更好的决策,促进收入增长,改善服务,降低成本提供有力支撑!

典型分布式文件系统概述

分布式文件系统概述(一) 杨栋 yangdonglee@https://www.doczj.com/doc/cc5161324.html, 2006-12 摘要 文件系统是操作系统用来组织磁盘文件的方法和数据结构。传统的文件系统指各种UNIX平台的文件系统,包括UFS、FFS、EXT2、XFS等,这些文件系统都是单机文件系统,也称本地文件系统。随着网络的兴起,为了解决资源共享问题,出现了分布式文件系统。分布式文件系统是指文件系统管理的物理存储资源不一定直接连接在本地节点上,而是通过计算机网络与节点相连。本文1简要回顾了本地文件系统,然后按照发展例程大致介绍了2006年之前各时期主要的分布式文件系统,最后从设计目标、体系结构及关键技术等方面比较了各个分布式文件系统的异同。目前很火的Hadoop文件系统、S3文件系统都是从NFS等早期文件系统一步步演化而来的,了解分布式文件系统的历史,有助于大家更加深刻地领会分布式文件系统的精髓。 1本文写于2006年底,借鉴了别人的大量资料,目的是为了与同学们分享分布式文件系统的发展史。笔者在硕士期间跟随中科院计算所的孟老师、熊老师和唐荣锋进行分布式文件系统的研究和开发。分布式文件系统源远流长,本文只是选择了其发展史上的部分实例进行简单描述,由于笔者水平十分有限,错误之处难免很多,各位同学发现问题之后麻烦回复邮件到yangdonglee@https://www.doczj.com/doc/cc5161324.html,,我会尽全力完善,或者请各位同学自行修正。笔者目前在百度进行云计算方面的研究和开发,希望有兴趣的同学一起进行探讨。

目录 1.引言 (5) 2.本地文件系统 (5) 2.1FFS (6) 2.2LFS (6) 2.3Ext3 (7) 3.分布式文件系统 (7) 3.1 发展历程 (7) 3.2分布式文件系统分类 (8) 3.2.1 实现方法 (8) 3.2.2研究状况 (8) 3.3 NFS (9) 3.3.1概述 (9) 3.3.2 体系结构 (9) 3.3.3 通信机制 (10) 3.3.4进程 (10) 3.3.5 命名 (10) 3.3.6 同步机制 (11) 3.3.7 缓存和复制 (11) 3.3.8 容错性 (12) 3.3.9 安全性 (13) 3.4 AFS、DFS、Coda和InterMezzo (13) 3.5 SpriteFS和Zebra (14) 3.6xFS (16) 3.6.1 概述 (16) 3.6.2 体系结构 (16) 3.6.3 通信 (16) 3.6.4 进程 (17) 3.6.5 命名 (18) 3.6.6 缓存 (19)

Hadoop分布式文件系统方案

Hadoop分布式文件系统:架构和设计要点 Hadoop分布式文件系统:架构和设计要点 原文:https://www.doczj.com/doc/cc5161324.html,/core/docs/current/hdfs_design.html 一、前提和设计目标 1、硬件错误是常态,而非异常情况,HDFS可能是有成百上千的server组成,任何一个组件都有可能一直失效,因此错误检测和快速、自动的恢复是HDFS的核心架构目标。 2、跑在HDFS上的应用与一般的应用不同,它们主要是以流式读为主,做批量处理;比之关注数据访问的低延迟问题,更关键的在于数据访问的高吞吐量。 3、HDFS以支持大数据集合为目标,一个存储在上面的典型文件大小一般都在千兆至T字节,一个单一HDFS实例应该能支撑数以千万计的文件。 4、 HDFS应用对文件要求的是write-one-read-many访问模型。一个文件经过创建、写,关闭之后就不需要改变。这一假设简化了数据一致性问题,使高吞吐量的数据访问成为可能。典型的如MapReduce框架,或者一个web crawler应用都很适合这个模型。 5、移动计算的代价比之移动数据的代价低。一个应用请求的计算,离它操作的数据越近就越高效,这在数据达到海量级别的时候更是如此。将计算移动到数据附近,比之将数据移动到应用所在显然更好,HDFS提供给应用这样的接口。 6、在异构的软硬件平台间的可移植性。 二、Namenode和Datanode HDFS采用master/slave架构。一个HDFS集群是有一个Namenode和一定数目的Datanode 组成。Namenode是一个中心服务器,负责管理文件系统的namespace和客户端对文件的访问。Datanode在集群中一般是一个节点一个,负责管理节点上它们附带的存储。在部,一个文件其实分成一个或多个block,这些block存储在Datanode集合里。Namenode执行文件系统的namespace操作,例如打开、关闭、重命名文件和目录,同时决定block到具体Datanode节点的映射。Datanode在Namenode的指挥下进行block的创建、删除和复制。Namenode和Datanode 都是设计成可以跑在普通的廉价的运行linux的机器上。HDFS采用java语言开发,因此可以部署在很大围的机器上。一个典型的部署场景是一台机器跑一个单独的Namenode节点,集群中的其他机器各跑一个Datanode实例。这个架构并不排除一台机器上跑多个Datanode,不过这比较少见。

分布式文件系统架构设计(20201126073806)

分布式文件系统架构设计 1. 前言...................................................... 3.

2. HDFS1 (3) 3. HDFS2 (5) 4. HDFS3 ............................................................................................. 1 1 5. 结语..................................................... 1.5

1. 刖言 Hadoop 是一个由Apache基金会所开发的分布式系统基础架构。用户可以在不了解分布式底层细节的情况下,开发分布式程序。充分利用集群的威力进行高速运算和存储。 Hadoop 实现了一个分布式文件系统(Hadoop Distributed File System ),简称HDFS,解 决了海量数据存储的问题;实现了一个分布式计算引擎MapReduce ,解决了海量数据如何计 算的问题;实现了一个分布式资源调度框架YARN,解决了资源调度,任务管理的问题。而我 们今天重点给大家介绍的是Hadoop 里享誉世界的优秀的分布式文件系统-HDFS。 Hadoop 重要的比较大的版本有:Hadoop1 ,Hadoop2 , hadoop3 。同时也相对应的有HDFS1 ,HDFS2,HDFS3三个大版本。后面的HDFS的版本,都是对前一个版本的架构进行了调整优 化,而在这个调整优化的过程当中都是解决上一个版本的架构缺陷,然而这些低版本的架构缺陷也是我们在平时工作当中会经常遇到的问题,所以这篇文章一个重要的目的就是通过给大家介绍HDFS不同版本的架构演进,通过学习高版本是如何解决低版本的架构问题从而来提升我 们的系统架构能力。 2. HDFS1

分布式文件系统DFS使用方法总结(超详细)

DFS使用方法总结(超详细) 使用分布式文件系统 (DFS),系统管理员可以使用户方便地访问和管理物理上分布在网络各处的文件。通过DFS,可以使分布在多个服务器上的文件如同位于网络上的一个位置一样显示在用户面前。 您可采用两种方式实施分布式文件系统:一种是独立的根目录分布式文件系统,另一种是域分布式文件系统。 独立的DFS根目录: 不使用 Active Directory。 至多只能有一个根目录级别的目标。 使用文件复制服务不能支持自动文件复制。 通过服务器群集支持容错。 域DFS根目录: 必须宿主在域成员服务器上。 使它的DFS名称空间自动发布到 Active Directory 中。 可以有多个根目录级别的目标。 通过 FRS 支持自动文件复制。 通过 FRS 支持容错。 分布式文件系统 (DFS) 映射由一个DFS根目录、一个或多个DFS链接以及指向一个或多个目标的引用组成。 DFS根目录所驻留的域服务器称为主服务器。通过在域中的其他服务器上创建根目标,可以复制DFS根目录。这将确保在主服务器不可用时,文件仍可使用。因为域分布式文件系统的主服务器是域中的成员服务器,所以默认情况下,DFS映射将自动发布到 Active Directory 中,从而提供了跨越主服务器的DFS拓扑同步。这反过来又对DFS根目录提供了容错性,并支持目标的可选复制。通过向DFS根目录中添加DFS链接,您可扩展DFS映射。Windows Server 2003 家族对DFS映射中分层结构的层数的唯一限制是对任何文件路径最多使用 260 个字符。新DFS链接可以引用具有或没有子文件夹的目标,或引用整个Windows Server 2003 家族卷。 创建DFS根目录 使用DFS管理工具,您可以指定某个目标,指派它为DFS根目录。除了访问该目标外,用户还可以访问该目标的任何子文件夹。使用 Windows Server 2003 Enterprise Edition 或Windows Server 2003 Datacenter Edition 时,您可在单独计算机上作为多个DFS根目录的宿主。由于DFS Active Directory 对象的大小,大型的基于域的DFS名称空间可能会显著地增加网络传输量。因此,建议您为域根使用的DFS链接的个数少于 5000。建议在运行 Windows Server 2003 的服务器上的独立的根目录的最大名称空间为 50,000 个链接。 如何创建DFS根目录: 1.打开分布式文件系统。 2.在“操作”菜单上,单击“新建根目录”。

3种分布式文件系统

第一部分CEPH 1.1 特点 Ceph最大的特点是分布式的元数据服务器通过CRUSH,一种拟算法来分配文件的locaiton,其核心是 RADOS(resilient automatic distributed object storage),一个对象集群存储,本身提供对象的高可用,错误检测和修复功能。 1.2 组成 CEPH文件系统有三个主要模块: a)Client:每个Client实例向主机或进程提供一组类似于POSIX的接口。 b)OSD簇:用于存储所有的数据和元数据。 c)元数据服务簇:协调安全性、一致性与耦合性时,管理命名空间(文件名和 目录名) 1.3 架构原理 Client:用户 I/O:输入/输出 MDS:Metadata Cluster Server 元数据簇服务器 OSD:Object Storage Device 对象存储设备

Client通过与OSD的直接通讯实现I/O操作。这一过程有两种操作方式: 1. 直接通过Client实例连接到Client; 2. 通过一个文件系统连接到Client。 当一个进行打开一个文件时,Client向MDS簇发送一个请求。MDS通过文件系统层级结构把文件名翻译成文件节点(inode),并获得节点号、模式(mode)、大小与其他文件元数据。注意文件节点号与文件意义对应。如果文件存在并可以获得操作权,则MDS通过结构体返回节点号、文件长度与其他文件信息。MDS同时赋予Client操作权(如果该Client还没有的话)。目前操作权有四种,分别通过一个bit表示:读(read)、缓冲读(cache read)、写(write)、缓冲写(buffer write)。在未来,操作权会增加安全关键字,用于client向OSD证明它们可以对数据进行读写(目前的策略是全部client 都允许)。之后,包含在文件I/O中的MDS被用于限制管理能力,以保证文件的一致性与语义的合理性。 CEPH产生一组条目来进行文件数据到一系列对象的映射。为了避免任何为文件分配元数据的需要。对象名简单的把文件节点需要与条目号对应起来。对象复制品通过CRUSH(著名的映射函数)分配给OSD。例如,如果一个或多个Client打开同一个文件进行读操作,一个MDS会赋予他们读与缓存文件内容的能力。通过文件节点号、层级与文件大小,Client可以命名或分配所有包含该文件数据的对象,并直接从OSD簇中读取。任何不存在的对象或字节序列被定义为文件洞或0。同样的,如果Client打开文件进行写操作。它获得使用缓冲写的能力。任何位置上的数据都被写到合适的OSD上的合适的对象中。Client 关闭文件时,会自动放弃这种能力,并向MDS提供新的文件大小(写入时的最大偏移)。它重新定义了那些存在的并包含文件数据的对象的集合。 CEPH的设计思想有一些创新点主要有以下两个方面: 第一,数据的定位是通过CRUSH算法来实现的。

分布式文件系统研究-GFS

分布式文件系统研究16:Global File System 分类:技术日志 前段时间比较忙,好久没发技术文章了,几天来一个,嘿嘿 Global File System 简介 GFS(Global File System)是Minnesota大学开发的基于SAN的共享存储的机群文件系统,后来Sis tina公司将GFS产品化。GFS在很长一段时间都是以源代码开放软件的形式出现的,后来由于Sistina希望通过向用户提供支持和服务的计划未能取得成功,为了要促进自己的财务收入,Sistina在2001年将GFS 变成了一种“专有软件”。Red Hat公司收购Sistina之后,在遵循GPL协议(General Public License)的条件下履行诺言公开了GFS的源代码。现在,GFS的全名被称为“红帽全球文件系统”(Red Hat Global File System ,GFS)的软件,每台服务器每年收取2200美元的费用。 可能是redhat为了更好的收取服务费的缘故,有关GFS的文档真是少之又少,我只能从网上一些零星的资料来看看GFS的概貌。 框架 GFS最初是在IRIX上开发的,后来移植到LINUX上,并开放源码。基本框架如下图所示。 图1 GFS的基本框架图 通过使用GFS,多台服务器可以共用一个文件系统来存储文件。信息既可以存储在服务器上,也可以存储在一个存储局域网络上。 GFS与GPFS结构相似,但它是全对称的机群文件系统,没有服务器,因而没有性能瓶颈和单一故障点。GFS将文件数据缓存于节点的存储设备中,而不是缓存在节点的内存中。并通过设备锁来同步不同节点对文件的访问,保持UNIX文件共享语义。GFS实现了日志,节点失效可以快速恢复。GFS使用SCSI

分布式文件系统研究

分布式文件系统研究 由于工作性质的关系,我觉得自己很有必要对当今主流的分布式文件系统(Distributed File System,DFS)做系统的研究,总结优缺点,为下一步的工作提供必要的参考。因此,我动手搜集了不少资料,并进行了很初步的学习,以后我会把自己对DFS的学习心得整理起来,陆续放到博客上来。这就当是开篇吧,嘿嘿 概述 文件系统是操作系统的一个重要组成部分,通过对操作系统所管理的存储空间的抽象,向用户提供统一的、对象化的访问接口,屏蔽对物理设备的直接操作和资源管理。 根据计算环境和所提供功能的不同,文件系统可划分为四个层次,从低到高依次是:单处理器单用户的本地文件系统,如DOS的文件系统;多处理器单用户的本地文件系统,如OS/2的文件系统;多处理器多用户的本地文件系统,如Unix的本地文件系统;多处理器多用户的分布式文件系统,如Lustre文件系统。 本地文件系统(Local File System)是指文件系统管理的物理存储资源直接连接在本地节点上,处理器通过系统总线可以直接访问。分布式文件系统(Distributed File System)是指文件系统管理的物理存储资源不一定直接连接在本地节点上,而是通过计算机网络与节点相连。 由于互联网应用的不断发展,本地文件系统由于单个节点本身的局限性,已经很难满足海量数据存取的需要了,因而不得不借助分布式文件系统,把系统负载转移到多个节点上。 传统的分布式文件系统(如NFS)中,所有数据和元数据存放在一起,通过单一的存储服务器提供。这种模式一般称之为带内模式(In-band Mode)。随着客户端数目的增加,服务器就成了整个系统的瓶颈。因为系统所有的数据传输和元数据处理都要通过服务

7种分布式文件系统介绍

FastDFS (7) Fastdfs简介 (7) Fastdfs系统结构图 (7) FastDFS和mogileFS的对比 (8) MogileFS (10) Mogilefs简介 (10) Mogilefs组成部分 (10) 0)数据库(MySQL)部分 (10) 1)存储节点 (11) 2)trackers(跟踪器) (11) 3)工具 (11) 4)Client (11) Mogilefs的特点 (12) 1. 应用层——没有特殊的组件要求 (12) 2. 无单点失败 (12) 3. 自动的文件复制 (12) 4. “比RAID好多了” (12) 5. 传输中立,无特殊协议 (13) 6.简单的命名空间 (13) 7.不用共享任何东西 (13) 8.不需要RAID (13)

9.不会碰到文件系统本身的不可知情况 (13) HDFS (14) HDFS简介 (14) 特点和目标 (14) 1. 硬件故障 (14) 2. 流式的数据访问 (14) 3. 简单一致性模型 (15) 4. 通信协议 (15) 基本概念 (15) 1. 数据块(block) (15) 2. 元数据节点(Namenode)和数据节点(datanode) . 16 2.1这些结点的用途 (16) 2.2元数据节点文件夹结构 (17) 2.3文件系统命名空间映像文件及修改日志 (18) 2.4从元数据节点的目录结构 (21) 2.5数据节点的目录结构 (21) 文件读写 (22) 1.读取文件 (22) 1.1 读取文件示意图 (22) 1.2 文件读取的过程 (23) 2.写入文件 (24) 2.1 写入文件示意图 (24)

常见的分布式文件系统

常见的分布式文件系统有,GFS、HDFS、Lustre 、Ceph 、GridFS 、mogileFS、TFS、FastDFS等。各自适用于不同的领域。它们都不是系统级的分布式文件系统,而是应用级的分布式文件存储服务。 Google学术论文,这是众多分布式文件系统的起源 ================================== Google File System(大规模分散文件系统) MapReduce (大规模分散FrameWork) BigTable(大规模分散数据库) Chubby(分散锁服务) 一般你搜索Google_三大论文中文版(Bigtable、 GFS、 Google MapReduce)就有了。做个中文版下载源:https://www.doczj.com/doc/cc5161324.html,/topics/download/38db9a29-3e17-3dce-bc93-df9286081126 做个原版地址链接: https://www.doczj.com/doc/cc5161324.html,/papers/gfs.html https://www.doczj.com/doc/cc5161324.html,/papers/bigtable.html https://www.doczj.com/doc/cc5161324.html,/papers/mapreduce.html GFS(Google File System) -------------------------------------- Google公司为了满足本公司需求而开发的基于Linux的专有分布式文件系统。。尽管Google公布了该系统的一些技术细节,但Google并没有将该系统的软件部分作为开源软件发布。 下面分布式文件系统都是类 GFS的产品。

WIN2003下建立分布式文件系统的操作

WIN2003下建立分布式文件系统的操作 一、创建DFS根 使用分布式文件系统配置DFS分为两步:创建DFS根、创建DFS 链接; 单击开始-管理工具-分布式文件系统,在弹出的页面中右击新建根目录,如图所示; 弹出新建根目录向导;单击下一步;选择根目录类型,如果有AD域建议选择域根目录,如下图所示; 独立根的配置信息存储在根服务器的注册表信息中,如果独立根服务器不可用,会导致DFS不可用。不支持容错。

域根的配置信息存储在AD中,并复制到当前域中所有DC中,以实现容错性,当根服务器不可用时,其它服务器仍可向客户端传送DFS 信息。显然,域根是更加安全的方案,但需要AD域支持。建议连接数不要超过5000个。 单击下一步,输入域名信息,

输入服务器名称;点击浏览查找选择根目录的服务器名称;如图所示;

输入根目录名称和注释;根目录名称即共享访问的顶级的共享名称。如果共享文件夹存在,则直接使用,如果共享文件夹没有创建,便会自动创建一个共享文件夹。 在根目录共享中,选择指定的共享文件夹,如果文件未共享,向导会自动创建对应的文件;根目录建立完成后,分布式文件系统中会相应生成DFS根目录; 创建DFS链接 建立好DFS根目录后,为了能让DFS正常运行,还需建立DFS链接才能完成整个DFS的建立。即在DFS根上右击新建DFS链接,为链接起个名字并指向适当的的共享资源。如图,

在新建链接页面中输入链接名称和目标路径;链接名称即为客户端希望看到的根目录下的共享文件夹的名称。目标路径为服务器中已经共享的文件夹路径,如图所示; 对客户端缓存引用所需时间的解释:客户端对获得的引用进行缓存,对于独立的根目录默认的缓存时间是300秒,对于域根目录默认的缓存时间是1800秒。通常情况无需修改缓存时间配置,如果命名空间中的文件夹目标变更频繁,应考虑减少缓存时间;但减少缓存时间会增加域控制器和命名空间服务器的负载并增加网络访问流量。

分布式文件系统综述

Software Engineering and Applications 软件工程与应用, 2017, 6(2), 21-27 Published Online April 2017 in Hans. https://www.doczj.com/doc/cc5161324.html,/journal/sea https://https://www.doczj.com/doc/cc5161324.html,/10.12677/sea.2017.62003 文章引用: 杜振南, 朱崇军. 分布式文件系统综述[J]. 软件工程与应用, 2017, 6(2): 21-27. A Survey of Distributed File System Zhennan Du, Chongjun Zhu College of Computer Science, National University of Defense Technology, Changsha Hunan Received: Mar. 27th , 2017; accepted: Apr. 10th , 2017; published: Apr. 14th , 2017 Abstract The file system is an important part of the computer system. With the development of personal computer and network technology, the generation of distributed file system has effectively solved the problem of infinite growth of massive information storage. This paper summarizes the origin of the distributed file system and comprehensively analyzes and organizes the architecture of several typical distributed file systems by consulting a large number of documents. Keywords Distributed File System, Storage Technology 分布式文件系统综述 杜振南,朱崇军 国防科学技术大学计算机学院,湖南 长沙 收稿日期:2017年3月27日;录用日期:2017年4月10日;发布日期:2017年4月14日 摘 要 文件系统是计算机系统的重要组成部分,随着个人计算机和网络技术的发展,分布式文件系统的产生有效解决了无限增长的海量信息存储问题。本文通过查阅大量文献,概述了分布式文件系统的起源并综合分析整理了几种典型分布式文件系统的体系架构。 关键词 分布式文件系统,存储技术

分布式文件系统、集群文件系统、并行文件系统

分布式文件系统、集群文件系统、并行文件系统,这三种概念很容易混淆,实际中大家也经常不加区分地使用。总是有人问起这三者的区别和联系,其实它们之间在概念上的确有交叉重叠的地方,但是也存在显著不同之处。分布式文件系统自然地,分布式是重点,它是相对与本地文件系统而言的。分布式文件系统通常指C/S架构或网络文件系统,用户数据没有直接连接到本地主机,而是存储在远程存储服务器上。NFS/CIFS是最为常见的分布式文件系统,这就是我们说的NAS系统。分布式文件系统中,存储服务器的节点数可能是1个(如传统NAS),也可以有多个(如集群NAS)。对于单个节点的分布式文件系统来说,存在单点故障和性能瓶颈问题。除了NAS以外,典型的分布式文件系统还有AFS,以及下面将要介绍的集群文件系统(如Lustre, GlusterFS, PVFS2等)。集群文件系统集群主要分为高性能集群HPC(High Performance Cluster)、高可用集群HAC(High Availablity Cluster)和负载均衡集群LBC(Load Balancing Cluster)。集群文件系统是指协同多个节点提供高性能、高可用或负载均衡的文件系统,它是分布式文件系统的一个子集,消除了单点故障和性能瓶问题。对于客户端来说集群是透明的,它看到是一个单一的全局命名空间,用户文件访问请求被分散到所有集群上进行处理。此外,可扩展性(包括Scale-Up和Scale-Out)、可靠性、易管理等也是集群文件系统追求的目标。在元数据管理方面,可以采用专用的服务器,也可以采用服务器集群,或者采用完全对等分布的无专用元数据服务器架构。目前典型的集群文件系统有SONAS, ISILON, IBRIX, NetAPP-GX, Lustre, PVFS2, GlusterFS, Google File System, LoongStore, CZSS等。并行文件系统这种文件系统能够支持并行应用,比如MPI。在并行文件系统环境下,所有客户端可以在同一时间并发读写同一个文件。并发读,大部分文件系统都能够实现。并发写实现起来要复杂许多,既要保证数据一致性,又要最大限度提高并行性,因此在锁机制方面需要特别设计,如细粒度的字节锁。通常SAN 共享文件系统都是并行文件系统,如GPFS、StorNext、GFS、BWFS,集群文件系统大多也是并行文件系统,如Lustre, Panasas等。如何区分?区分这三者的重点是分布式、集群、并行三个前缀关键字。简单来说,非本地直连的、通过网络连接的,这种为分布式文件系统;分布式文件系统中,服务器节点由多个组成的,这种为集群文件系统;支持并行应用(如MPI)的,这种为并行文件系统。在上面所举的例子中也可以看出,这三个概念之间具有重叠之处,比如Lustre,它既是分布式文件系统,也是集群和并行文件系统。但是,它们也有不同之处。集群文件系统是分布式文件系统,但反之则不成立,比如NAS、AFS。SAN文件系统是并行文件系统,但可能不是集群文件系统,如StorNext。GFS、HDFS之类,它们是集群文件系统,但可能不是并行文件系统。实际中,三者概念搞理清后,分析清楚文件系统的特征,应该还是容易正确地为其划分类别的。

实战创建基于域的分布式文件系统DFS

实战:创建基于域的分布式文件系统(DFS) 如果局域网中有多台服务器,并且共享文件夹也分布在不同的服务器上,这就不利于管理员的管理和用户的访问。而使用分布式文件系统,系统管理员就可以把不同服务器上的共享文件夹组织在一起,构建成一个目录树。这在用户看来,所有共享文件仅存储在一个地点,只需访问一个共享的DFS根目录,就能够访问分布在网络上 的文件或文件夹,而不必知道这些文件的实际物理位置。 DFS复制 DFS 复制是一种有效的多主机复制引擎,可用于保持跨有限带宽网络连接的服务器之间的文件夹同步。它将文件复制服务(FRS) 替换为用于DFS 命名空间以及用于复制使用Windows Server 2008 域功能级别的域中的Active Directory 域服务(AD DS) SYSVOL 文件夹的复制引擎。 DFS 复制使用一种称为远程差分压缩(RDC) 的压缩算法。RDC 检测对文件中数据的更改,并使DFS 复制仅复制已更改文件块而非整个文件。 若要使用DFS 复制,必须创建复制组并将已复制文件夹添加到组。复制组、已复制文件夹和成员在下图中进行了说明。

此图所示复制组是一组称为“成员”的服务器,它参与一个或多个已复制文件夹的复制。“已复制文件夹”是在每个成员上保持同步的文件夹。图中有两个已复制文件夹:Projects 和Proposals。每个已复制文件夹中的数据更改时,将通过复制组成员之间的连接复制更改。所有成员之间的连接构成复制拓扑。 如果在一个复制组中创建多个已复制文件夹,可以简化部署已复制文件夹的过程,因为该复制组的拓扑、计划和带宽限制将应用于每个已复制文件夹。若要部署其他已复制文件夹,可以使用Dfsradmin.exe 或按照向导中的说明来定义新的已复制文件夹的本地路径和权限。 每个已复制文件夹具有唯一的设置,例如文件和子文件夹筛选器,以便可以为每个已复制文件夹筛选出不同的文件和子文件夹。 存储在每个成员上的已复制文件夹可以位于成员中的不同卷上,已复制文件夹不必是共享文件夹也不必是命名空间的一部分。但是,

相关主题
文本预览
相关文档 最新文档