登录
首页精彩阅读大数据开发之深入HDFS​_数据分析师
大数据开发之深入HDFS​_数据分析师
2014-11-18
收藏

大数据开发之深入HDFS_数据分析师

数据集的大小超过一台独立的物理计算机的存储能力时,就有必要对它进行分区(partition)并存储到若干台单独的计算机上。管理网络中跨多台计算机存储的文件系统称为分布式文件系统(distributed filesystem)。该系统架构于网络之上,势必会引入网络编程的复杂性,因此分布式文件系统比普通磁盘文件系统更为复杂。例如,使文件系统能够容忍节点故障且不丢失任何数据,就是一个极大的挑战。

Hadoop有一个称为HDFS的分布式系统,即Hadoop Distributed Filesystem。在非正式文档或旧文档以及配置文件中,有时也简称为DFS,它们是一回事儿。HDFSHadoop的旗舰级文件系统,同时也是本章的重点,但实际上Hadoop是一个综合性的文件系统抽象,因此下面我们也将看到Hadoop集成其他文件系统的方法(如本地文件系统和Amazon S3系统)。

3.1  HDFS的设计 

HDFS以流式数据访问模式来存储超大文件,运行于商用硬件集群上。让我们仔细看看下面的描述。


  • 超大文件 “超大文件”在这里指具有几百MB、几百GB甚至几百TB大小的文件。目前已经有存储PB级数据的Hadoop 集群了。
  • 流式数据访问 HDFS的构建思路是这样的:一次写入、多次读取是最高效的访问模式。数据集通常由数据源生成或从数据源复制而来,接着长时间在此数据集上进行各种分析。每次分析都将涉及该数据集的大部分数据甚至全部,因此读取整个数据集的时间延迟比读取第一条记录的时间延迟更重要。
  • 商用硬件 Hadoop并不需要运行在昂贵且高可靠的硬件上。它是设计运行在商用硬件(在各种零售店都能买到的普通硬件)的集群上的,因此至少对于庞大的集群来说,节点故障的几率还是非常高的。HDFS遇到上述故障时,被设计成能够继续运行且不让用户察觉到明显的中断。同样,那些不适合在HDFS上运行的应用也值得研究。目前某些应用领域并不适合在HDFS上运行,不过以后可能会有所改进。
  • 低时间延迟的数据访问要求低时间延迟数据访问的应用,例如几十毫秒范围,不适合在HDFS上运行。记住,HDFS是为高数据吞吐量应用优化的,这可能会以提高时间延迟为代价。目前,对于低延迟的访问需求,HBase(参见第12 章)是更好的选择。
  • 大量的小文件 由于namenode将文件系统的元数据存储在内存中,因此该文件系统所能存储的文件总数受限于namenode的内存容量。根据经验,每个文件、目录和数据块的存储信息大约占150字节。因此,举例来说,如果有一百万个文件,且每个文件占一个数据块,那至少需要300 MB 的内存。尽管存储上百万个文件是可行的,但是存储数十亿个文件就超出了当前硬件的能力。
  • 多用户写入,任意修改文件 HDFS中的文件可能只有一个writer,而且写操作总是将数据添加在文件的末尾。它不支持具有多个写入者的操作,也不支持在文件的任意位置进行修改。可能以后会支持这些操作,但它们相对比较低效。


3.2  HDFS的概念 

3.2.1  数据块 

每个磁盘都有默认的数据块大小,这是磁盘进行数据读/写的最小单位。构建于单个磁盘之上的文件系统通过磁盘块来管理该文件系统中的块,该文件系统块的大小可以是磁盘块的整数倍。文件系统块一般为几千字节,而磁盘块一般为512字节。这些信息——文件系统块大小——对于需要读/写文件的文件系统用户来说是透明的。尽管如此,系统仍然提供了一些工具(如df和fsck)来维护文件系统,由它们对文件系统中的块进行操作。

HDFS同样也有块(block)的概念,但是大得多,默认为64 MB。与单一磁盘上的文件系统相似,HDFS上的文件也被划分为块大小的多个分块(chunk),作为独立的存储单元。但与其他文件系统不同的是,HDFS中小于一个块大小的文件不会占据整个块的空间。如果没有特殊指出,本书中提到的“块”特指HDFS中的块。

为何HDFS 中的块如此之大?

HDFS的块比磁盘的块大,其目的是为了最小化寻址开销。如果块设置得足够大,从磁盘传输数据的时间会明显大于定位这个块开始位置所需的时间。因而,传输一个由多个块组成的文件的时间取决于磁盘传输速率。

我们来做一个速算,如果寻址时间约为10ms,而传输速率为100 MB/s,为了使寻址时间仅占传输时间的1%,我们要将块大小设置约为100 MB。默认的块大小实际为64 MB,但是很多情况下HDFS使用128 MB的块设置。以后随着新一代磁盘驱动器传输速率的提升,块的大小将被设置得更大。

但是这个数也不会设置得过大。MapReduce中的map任务通常一次只处理一个块中的数据,因此如果任务数太少(少于集群中的节点数量),作业的运行速度就会比较慢。

对分布式文件系统中的块进行抽象会带来很多好处。第一个最明显的好处是,一个文件的大小可以大于网络中任意一个磁盘的容量。文件的所有块并不需要存储在同一个磁盘上,因此它们可以利用集群上的任意一个磁盘进行存储。事实上,尽管不常见,但对于整个HDFS集群而言,也可以仅存储一个文件,该文件的块占满集群中所有的磁盘。

第二个好处是,使用抽象块而非整个文件作为存储单元,大大简化了存储子系统的设计。简化是所有系统的目标,但是这对于故障种类繁多的分布式系统来说尤为重要。将存储子系统控制单元设置为块,可简化存储管理(由于块的大小是固定的,因此计算单个磁盘能存储多少个块就相对容易)。同时也消除了对元数据的顾虑(块只是存储数据的一部分——而文件的元数据,如权限信息,并不需要与块一同存储,这样一来,其他系统就可以单独管理这些元数据)。

不仅如此,块还非常适合用于数据备份进而提供数据容错能力和提高可用性。将每个块复制到少数几个独立的机器上(默认为3个),可以确保在块、磁盘或机器发生故障后数据不会丢失。如果发现一个块不可用,系统会从其他地方读取另一个复本,而这个过程对用户是透明的。一个因损坏或机器故障而丢失的块可以从其他候选地点复制到另一台可以正常运行的机器上,以保证复本的数量回到正常水平。参见4.1节对数据完整性的讨论,进一步了解如何应对数据损坏。同样,有些应用程序可能选择为一些常用的文件块设置更高的复本数量进而分散集群中的读取负载。 

与磁盘文件系统相似,HDFS中fsck指令可以显示块信息。例如,执行以下命令将列出文件系统中各个文件由哪些块构成(参见10.1.4.2节): 

  1. % hadoop fsck / -files -blocks   

3.2.2  namenode和datanode 

和多个datanode(工作者)。namenode管理文件系统的命名空间。它维护着文件系统树及整棵树内所有的文件和目录。这些信息以两个文件形式永久保存在本地磁盘上:命名空间镜像文件和编辑日志文件。namenode也记录着每个文件中各个块所在的数据节点信息,但它并不永久保存块的位置信息,因为这些信息会在系统启动时由数据节点重建。

客户端(client)代表用户通过与namenode和datanode交互来访问整个文件系统。客户端提供一个类似于POSIX(可移植操作系统界面)的文件系统接口,因此用户在编程时无需知道namenode和datanode也可实现其功能。

datanode是文件系统的工作节点。它们根据需要存储并检索数据块(受客户端或namenode调度),并且定期向namenode发送它们所存储的块的列表。

没有namenode,文件系统将无法使用。事实上,如果运行namenode服务的机器毁坏,文件系统上所有的文件将会丢失,因为我们不知道如何根据datanode的块重建文件。因此,对namenode实现容错非常重要,Hadoop为此提供两种机制。

第一种机制是备份那些组成文件系统元数据持久状态的文件。Hadoop可以通过配置使namenode在多个文件系统上保存元数据的持久状态。这些写操作是实时同步的,是原子操作。一般的配置是,将持久状态写入本地磁盘的同时,写入一个远程挂载的网络文件系统(NFS)。

另一种可行的方法是运行一个辅助namenode,但它不能被用作namenode。这个辅助namenode的重要作用是定期通过编辑日志合并命名空间镜像,以防止编辑日志过大。这个辅助namenode一般在另一台单独的物理计算机上运行,因为它需要占用大量CPU时间与namenode相同容量的内存来执行合并操作。它会保存合并后的命名空间镜像的副本,并在namenode发生故障时启用。但是,辅助namenode保存的状态总是滞后于主节点,所以在主节点全部失效时,难免会丢失部分数据。在这种情况下,一般把存储在NFS上的namenode元数据复制到辅助namenode并作为新的主namenode运行。

详情参见10.1.1节对文件系统镜像与编辑日志的讨论。

3.2.3  联邦HDFS 

namenode在内存中保存文件系统中每个文件和每个数据块的引用关系,这意味着对于一个拥有大量文件的超大集群来说,内存将成为限制系统横向扩展的瓶颈(参见9.4.2节)。在2.x发行版本系列中引入的联邦HDFS允许系统通过添加namenode实现扩展,其中每个namenode管理文件系统命名空间中的一部分。例如,一个namenode可能管理/user目录下的所有文件,而另一个namenode可能管理/share目录下的所有文件。

在联邦环境下,每个namenode维护一个命名空间卷(namespace volume),包括命名空间的源数据和在该命名空间下的文件的所有数据块的数据块池。命名空间卷之间是相互独立的,两两之间并不相互通信,甚至其中一个namenode的失效也不会影响由其他namenode维护的命名空间的可用性。数据块池不再进行切分,因此集群中的datanode需要注册到每个namenode,并且存储着来自多个数据块池中的数据块。

要想访问联邦HDFS集群,客户端需要使用客户端挂载数据表将文件路径映射到namenode。该功能可以通过ViewFileSystem和viewfs://URI进行配置和管理。

3.2.4  HDFS的高可用性 

通过联合使用在多个文件系统中备份namenode的元数据和通过备用namenode创建监测点能防止数据丢失,但是依旧无法实现文件系统的高可用性。Namenode依旧存在单点失效(SPOF)的问题。如果namenode失效了,那么所有的客户端——包括MapReduce作业——均无法读、写或列 (list)文件,因为namenode是唯一存储元数据与文件到数据块映射的地方。在这一情况下,Hadoop系统无法提供服务直到有新的namenode上线。

在这样的情况下,要想从一个失效的namenode恢复,系统管理员得启动一个拥有文件系统元数据副本的新的namenode,并配置datanode和客户端以便使用这个新的namenode。新的namenode直到满足以下情形才能响应服务:1)将命名空间的映像导入内存中;2)重做编辑日志;3)接收到足够多的来自datanode的数据块报告并退出安全模式。对于一个大型并拥有大量文件和数据块的集群,namenode的冷启动需要30分钟,甚至更长时间。

系统恢复时间太长,也会影响到日常维护。事实上,namenode失效的可能性非常低,所以在实际应用中计划系统失效时间就显得尤为重要。

Hadoop的2.x发行版本系列针对上述问题在HDFS中增加了对高可用性(HA)的支持。在这一实现中,配置了一对活动-备用(active-standby) namenode。当活动namenode失效,备用namenode就会接管它的任务并开始服务于来自客户端的请求,不会有任何明显中断。实现这一目标需要在架构上做如下修改。


  • namenode之间需要通过高可用的共享存储实现编辑日志的共享。(在早期的高可用实现版本中,需要一个NFS过滤器来辅助实现,但是在后期版本中将提供更多的选择,比如构建于ZooKeeper之上的BookKeeper这样的系统。)当备用namenode接管工作之后,它将通读共享编辑日志直至末尾,以实现与活动namenode的状态同步,并继续读取由活动namenode写入的新条目。
  • datanode需要同时向两个namenode发送数据块处理报告,因为数据块的映射信息存储在namenode的内存中,而非磁盘。
  • 客户端需要使用特定的机制来处理namenode的失效问题,这一机制对用户是透明的。


在活动namenode失效之后,备用namenode能够快速(几十秒的时间)实现任务接管,因为最新的状态存储在内存中:包括最新的编辑日志条目和最新的数据块映射信息。实际观察到的失效时间略长一点(需要1分钟左右),这是因为系统需要保守确定活动namenode是否真的失效了。

在活动namenode失效且备用namenode也失效的情况下,当然这类情况发生的概率非常低,管理员依旧可以申明一个备用namenode并实现冷启动。这类情况并不会比非高可用(no-HA)的情况更差,并且从操作的角度讲这是一个进步,因为上述处理已是一个标准的处理过程并植入Hadoop中。

故障切换与规避 

一个称为故障转移控制器(failover_controller)的系统中有一个新实体管理着将活动namenode转移为备用namenode的转换过程。故障转移控制器是可插拔的,但其最初的实现是基于ZooKeeper的并由此确保有且仅有一个活动namenode。每一个namenode运行着一个轻量级的故障转移控制器,其工作就是监视宿主namenode是否失效(通过一个简单的心跳机制实现)并在namenode失效时进行故障切换。

管理员也可以手动发起故障转移,例如在进行日常维护时。这称为“平稳的故障转移”,因为故障转移控制器可以组织两个namenode有序切换角色。

但在非平稳故障转移的情况下,无法确切知道失效namenode是否已经停止运行。例如,在网速非常慢或者网络被分割的情况下,同样也可能激发故障转移,但是先前的活动namenode依然运行着并且依旧是活动namenode。高可用实现做了更进一步的优化,以确保先前活动的namenode不会执行危害系统并导致系统崩溃的操作——该方法称为“规避”(fencing)。系统引入了一系列的规避机制,包括杀死namenode进程,收回访问共享存储目录的权限(通常使用供应商指定的NFS命令),通过远程管理命令以屏蔽相应网络端口。诉诸的最后手段是,先前活动namenode可以通过一个相当形象的称为STONITH(shootthe other node in the head)的技术进行规避,该方法主要通过一个特定的供电单元对相应主机进行断电操作。

客户端的故障切换通过客户端类库实现透明处理。最简单的实现是通过客户端的配置文件实现故障切换的控制。HDFS URI使用一个逻辑主机名,该主机名映射到一对namenode地址(在配置文件中设置),客户端类库会访问每一个namenode地址直至处理完成。

3.3  命令行接口 

现在我们通过命令行交互来进一步认识HDFSHDFS还有很多其他接口,但命令行是最简单的,同时也是许多开发者最熟悉的。

参照附录A中伪分布模式下设置Hadoop的说明,我们先在一台机器上运行HDFS。稍后介绍如何在集群上运行HDFS,以提供伸缩性与容错性。

在我们设置伪分布配置时,有两个属性项需要进一步解释。第一项是fs.default.name,设置为hdfs://localhost/,用于设置Hadoop的默认文件系统。文件系统是由URI指定的,这里我们已使用hdfs URI来配置HDFSHadoop的默认文件系统。HDFS的守护程序通过该属性项来确定HDFS namenode的主机及端口。我们将在localhost默认端口8020上运行namenode。这样一来,HDFS客户端可以通过该属性得知namenode在哪里运行进而连接到它。

第二个属性dfs.replication,我们设为1,这样一来,HDFS就不会按默认设置将文件系统块复本设为3。在单独一个datanode上运行时,HDFS无法将块复制到3个datanode上,所以会持续给出块复本不足的警告。设置这个属性之后,就不会再有问题了。

文件系统的基本操作 

至此,文件系统已经可以使用了,我们可以执行所有常用的文件系统操作,例如,读取文件,新建目录,移动文件,删除数据,列出目录,等等。可以输入hadoop fs -help命令获取每个命令的详细帮助文件。

首先从本地文件系统将一个文件复制到HDFS

  1. % hadoop fs -copyFromLocal input/docs/quangle.txt   
  2. hdfs://localhost/user/tom/quangle.txt   

该命令调用Hadoop文件系统的shell命令fs,后者提供了一系列子命令,在这个例子中,我们执行的是-copyFromLocal。本地文件quangle.txt被复制到运行在localhost上的 HDFS实例中,路径为/user/tom/quangle.txt。事实上,我们可以简化命令格式以省略主机的URI并使用默认设置,即省略hdfs://localhost,因为该项已在core-site.xml中指定。

  1. % hadoop fs -copyFromLocal input/docs/quangle.txt /user/tom/quangle.txt   

我们也可以使用相对路径,并将文件复制到HDFS的home目录中,本例中为/user/tom: 

  1. % hadoop fs -copyFromLocal input/docs/quangle.txt quangle.txt  

我们把文件复制回本地文件系统,并检查是否一致: 

  1. % hadoop fs -copyToLocal quangle.txt quangle.copy.txt    
  2. % md5 input/docs/quangle.txt quangle.copy.txt    
  3.  MD5 (input/docs/quangle.txt) = a16f231da6b05e2ba7a339320e7dacd9    
  4.  MD5 (quangle.copy.txt) = a16f231da6b05e2ba7a339320e7dacd9   

MD5键值相同,表明这个文件在HDFS之旅中得以幸存并保存完整。 最后,我们看一下HDFS文件列表。我们新建一个目录看它在列表中是怎么显示的: 

  1. % hadoop fs -mkdir books    
  2. % hadoop fs -ls .    
  3. Found 2 items    
  4. drwxr-xr-x   - tom supergroup   0 2009-04-02 22:41 /user/tom/books    
  5. -rw-r--r--   1 tom supergroup   118 2009-04-02 22:29 /user/tom/quangle.txt   

返回的结果信息与Unix命令ls -l的输出结果非常相似,仅有细微差别。第1列显示的是文件模式。第2列是这个文件的备份数(这在传统Unix文件系统是没有的)。由于我们在整个文件系统范围内设置的默认复本数为1,所以这里显示的也都是1。这一列的开头目录为空,因为本例中没有使用复本的概念——目录作为元数据保存在namenode中,而非datanode中。第3列和第4列显示文件的所属用户和组别。第5列是文件的大小,以字节为单位,目录为0。第6列和第7列是文件的最后修改日期与时间。最后,第8列是文件或目录的绝对路径。 

HDFS中的文件访问权限

针对文件和目录,HDFS的权限模式与POSIX 非常相似。

一共提供三类权限模式:只读权限(r)、写入权限(w)和可执行权限(x)。读取文件或列出目录内容时需要只读权限。写入一个文件或是在一个目录上新建及删除文件或目录,需要写入权限。对于文件而言,可执行权限可以忽略,因为你不能在HDFS中执行文件(与POSIX不同),但在访问一个目录的子项时需要该权限。

每个文件和目录都有所属用户(owner)、所属组别(group)及模式(mode)。这个模式是由所属用户的权限、组内成员的权限及其他用户的权限组成的。

在默认情况下,可以通过正在运行进程的用户名和组名来唯一确定客户端的标识。但由于客户端是远程的,任何用户都可以简单地在远程系统上以其名义新建一个账户来进行访问。因此,作为共享文件系统资源和防止数据意外损失的一种机制,权限只能供合作团体中的用户使用,而不能用于在一个不友好的环境中保护资源。注意,最新版的Hadoop已经支持Kerberos用户认证,该认证去除了这些限制,详见第325页的“安全”小节。但是,除了上述限制之外,为防止用户或自动工具及程序意外修改或删除文件系统的重要部分,启用权限控制还是很重要的(这也是默认的配置,参见dfs.permissions属性)。

如果启用权限检查,就会检查所属用户权限,以确认客户端的用户名与所属用户是否匹配,另外也将检查所属组别权限,以确认该客户端是否是该用户组的成员;若不符,则检查其他权限。

这里有一个超级用户(super-user)的概念,超级用户是namenode进程的标识。对于超级用户,系统不会执行任何权限检查。

3.4  Hadoop文件系统 

Hadoop有一个抽象的文件系统概念,HDFS只是其中的一个实现。Java抽象类 org.apache.hadoop.fs.FileSystem定义了Hadoop 中的一个文件系统接口,并且该抽象类有几个具体实现,如表3-1所示。

表3-1.  Hadoop文件系统 

文件系统 URI方案 Java实现(均包含在org.apache.hadoop包中) 描述
Local file fs.LocalFileSystem 使用了客户端校验和的本地磁盘文件系统。没有使用校验和的本地磁盘文件系统RawLocalFileSystem。详情参见4.1.2节
HDFS hdfs hdfs.DistributedFileSystem Hadoop 的分布式文件系统。将HDFS设计成与MapReduce结合使用,可以实现高性能
HFTP Hftp hdfs.hftpFileSystem 一个在HTTP 上提供对HDFS 只读访问的文件系统(尽管名称为HFTP,但与FTP无关)。通常与distcp结合使用(参见3.8节),以实现在运行不同版本的HDFS的集群之间复制数据
HSFTP hsftp hdfs.HsftpFileSyste 在HTTPS 上提供对HDFS只读访问的文件系统(同上,与FTP 无关)
WebHDFS Webhdfs Hdfs.web.WebHdfsFileSystem 基于HTTP,对HDFS提供安全读写访问的文件系统。WebHDFS是为了替代HFTP和HSFTP而构建的
HAR har fs.HarFileSystem

一个构建在其他文件系统之上用于文件存档的文件系统。Hadoop存档文件系统通常用于需要将HDFS 中的文件进行存档时,以减少namenode内存的使用。参见3.9节

hfs(云存储) kfs fs.kfs.kosmosFileSystem CloudStore(其前身为Kosmos文件系统)是类似于HDFS或是谷歌的GFS的文件系统,用C++写。详情参见http://kosmosfs.sourceforge.net/
FTP ftp fs.ftp.FTPFileSystem 由FTP 服务器支持的文件系统
S3(原生) S3n fs.s3native.NativeS3FileSystem 由Amazon S3 支持的文件系统。参见http://wiki.apache.org/hadoop/AmazonS3
S3(基于块) S3 fs.sa.S3FileSystem 由Amazon S3 支持的文件系统,以块格式存储文件(与HDFS 很相似)以解决S3 的5 GB文件大小限制
分布式RAID hdfs hdfs.DistributedRaidFileSystem RAID版本的HDFS是为了存档而设计的。针对HDFS中的每个文件,创建一个(更小的)校验文件,并允许HDFS中的数据副本由3降为2,由此可以减少25%~30%的存储空间,但是数据丢失的概率保持不变。分布式RAID模式需要在集群中运行一个RaidNode后台进程
View viewfs viewfs.ViewFileSystem 针对其他Hadoop文件系统挂载的客户端表。通常用于联邦namenode创建挂载点。详情参见3.2.3节。
Hadoop 对文件系统提供了许多接口,它一般使用URI 方案来选取合适的文件系统实例进行交互。举例来说,我们在前一小节中遇到的文件系统命令行解释器可以操作所有的Hadoop 文件系统命令。要想列出本地文件系统根目录下的文件,可以输入以下命令: 

  1. % hadoop fs -ls file:///  

尽管运行的MapReduce程序可以访问任何文件系统(有时也很方便),但在处理大数据集时,建议你还是选择一个有数据本地优化的分布式文件系统,如HDFS(参见2.4节)。

接口 

Hadoop是用Java写的,通过Java API可以调用所有Hadoop文件系统的交互操作。例如,文件系统的命令解释器就是一个Java 应用,它使用Java 的FileSystem类来提供文件系统操作。其他一些文件系统接口也将在本小节中做简单介绍。这些接口通常与HDFS一同使用,因为Hadoop中的其他文件系统一般都有访问基本文件系统的工具(对于FTP,有FTP客户端;对于S3,有S3工具,等等),但它们大多数都能用于任何Hadoop 文件系统。

1. HTTP 

通过HTTP来访问HDFS有两种方法:直接访问,HDFS后台进程直接服务于来自客户端的请求;通过代理(一个对多个)访问,客户端通常使用DistributedFileSystem API访问HDFS。这两种方法如图3-1所示。 

图3-1. 通过HTTP直接访问HDFS或者通过多个HDFS代理访问HDFS 

在第一种情况中,由namenode内嵌的web服务器(运行在端口50070上)提供目录服务,目录列表以XML或者JSON格式存储,并且文件数据由datanode的web服务器(运行在端口50075上)以数据流的形式传输。 

原来那个的HTTP接口(HFTP和HSFTP)是只读的,但是新的WebHDFS实现支持所有的文件系统操作,包括Kerberos认证。WebHDFS必须通过将dfs.webhdfs.enalbe选项设置为真后才能启用,并且只有启用它之后,你才可以使用webhdfs URI。

第二种方法依靠一个或者多个独立代理服务器通过HTTP访问HDFS。(由于代理服务是无状态的,因此可以运行在标准的负载均衡器之后。)所有到集群的网络通信都需要经过代理。使用代理服务器后可以使用更严格的防火墙策略和带宽限制策略。通常情况下通过代理服务器,实现在不同数据中心中部署的Hadoop集群之间的数据传输。

原来那个的HDFS代理服务器(在src/contrib/hdfsproxy)是只读的并且客户端使用HSFTP Filesystem实现(hsftp URI)进行访问。从1.0.0版本开始,实现了一个称为HttpFS的新代理服务器(具备读和写的能力),并且提供了和WebHDFS的一样的HTTP接口,因此客户端可以通过webhdfsURI访问这两类接口。

在规范正式定义了WebHDFS中使用的HTTP REST API,以期望以后使用非Java语言编写的客户端有望直接使用这个API。

2. C语言 

Hadoop提供了一个名为libhdfs的C语言库,该语言库是Java,FileSystem接口类的一个镜像(它被写成访问HDFS的C语言库,但其实它可以访问全部Hadoop文件系统)。它使用Java原生接口(Java Native Interface,JNI)调用Java 文件系统客户端。

这个C语言API 与Java的API非常相似,但它的开发一般滞后于Java API,因此目前一些新的特性可能还不支持。可以在Hapdoop发行包的Libhdfs/docs/api目录找到CAPI的相关文档。

Hadoop 中自带预先编译好的32位Linux的libhdfs二进制编码,但对于其他平台,需要按照http://wiki.apache.org/hadoop/LibHDFS的教程自行编译。

3. FUSE 

用户空间文件系统(Filesystem in Userspace,FUSE)允许把按照用户空间实现的文件系统整合成一个Unix文件系统。通过使用Hadoop的Fuse-DFS功能模块,任何一个Hadoop 文件系统(不过一般为HDFS)均可以作为一个标准文件系统进行挂载。随后便可以使用Unix工具(如ls和cat)与该文件系统交互,还可以通过任意一种编程语言调用POSIX 库来访问文件系统。

Fuse-DFS是用C语言实现的,调用libhdfs并作为访问HDFS的接口。关于如何编译和运行Fuse-DFS的文档,可以在Hadoop发行版的src/contrib./fuse-dfs目录中找到。

3.5  Java接口 

在本小节中,我们要深入探索Hadoop的Filesystem类:它是与Hadoop的某一文件系统进行交互的API。虽然我们主要聚焦于HDFS实例,即DistributedFileSystem,但总体来说,还是应该集成FileSystem抽象类,并编写代码,使其在不同文件系统中可移植。这对测试你编写的程序非常重要,例如,你可以使用本地文件系统中的存储数据快速进行测试。

3.5.1  从Hadoop URL读取数据 

要从Hadoop 文件系统读取文件,最简单的方法是使用java.net.URL对象打开数据流,从中读取数据。具体格式如下:

  1. InputStream in = null;    
  2.  try {    
  3.       in = new URL(

数据分析咨询请扫描二维码

客服在线
立即咨询