您好,欢迎访问三七文档
当前位置:首页 > 商业/管理/HR > 信息化管理 > Hadoop中HDFS的实现代码分析
萝卜网()Hadoop中HDFS的实现代码分析一、简介Hadoop由ApacheSoftwareFoundation公司于2005年秋天作为Lucene的子项目Nutch的一部分正式引入。它受到最先由GoogleLab开发的MapReduce和GoogleFileSystem的启发。2006年3月份,MapReduce和NutchDistributedFileSystem(NDFS)分别被纳入称为Hadoop的项目中。Hadoop是最受欢迎的在Internet上对搜索关键字进行内容分类的工具,但它也可以解决许多要求极大伸缩性的问题。Hadoop为应用程序透明的提供了一组稳定/可靠的接口和数据运动。在Hadoop中实现了Google的MapReduce算法,它能够把应用程序分割成许多很小的工作单元,每个单元可以在任何集群节点上执行或重复执行。此外,Hadoop还提供一个分布式文件系统用来在各个计算节点上存储数据,并提供了对数据读写的高吞吐率。由于应用了map/reduce和分布式文件系统,使得Hadoop框架具有高容错性,它会自动处理失败节点。已经在具有600个节点的集群测试过Hadoop框架。Hadoop是一个能够对大量数据进行分布式处理的软件框架。但是Hadoop是以一种可靠、高效、可伸缩的方式进行处理的。Hadoop是可靠的,因为它假设计算元素和存储会失败,因此它维护多个工作数据副本,确保能够针对失败的节点重新分布处理。Hadoop是高效的,因为它以并行的方式工作,通过并行处理加快处理速度。Hadoop还是可伸缩的,能够处理PB级数据。此外,Hadoop依赖于社区服务器,因此它的成本比较低,任何人都可以使用。萝卜网()Hadoop带有用Java语言编写的框架,因此运行在Linux生产平台上是非常理想的。Hadoop上的应用程序也可以使用其他语言编写,比如C++。二、Hadoop-架构Hadoop有许多元素构成。最底部是HadoopDistributedFileSystem(HDFS),它存储Hadoop集群中所有存储节点上的文件。HDFS(对于本文)的上一层是MapReduce引擎,该引擎由JobTrackers和TaskTrackers组成。2.1、HDFS对外部客户机而言,HDFS就像一个传统的分级文件系统。可以创建、删除、移动或重命名文件,等等。但是HDFS的架构是基于一组特定的节点构建的(参见图1),这是由它自身的特点决定的。这些节点包括NameNode(仅一个),它在HDFS内部提供元数据服务;DataNode,它为HDFS提供存储块。由于仅存在一个NameNode,因此这是HDFS的一个缺点(单点失败)。图1.Hadoop集群的简化视图存储在HDFS中的文件被分成块,然后将这些块复制到多个计算机中萝卜网()(DataNode)。这与传统的RAID架构大不相同。块的大小(通常为64MB)和复制的块数量在创建文件时由客户机决定。NameNode可以控制所有文件操作。HDFS内部的所有通信都基于标准的TCP/IP协议。2.2、NameNodeNameNode是一个通常在HDFS实例中的单独机器上运行的软件。它负责管理文件系统名称空间和控制外部客户机的访问。NameNode决定是否将文件映射到DataNode上的复制块上。对于最常见的3个复制块,第一个复制块存储在同一机架的不同节点上,最后一个复制块存储在不同机架的某个节点上。实际的I/O事务并没有经过NameNode,只有表示DataNode和块的文件映射的元数据经过NameNode。当外部客户机发送请求,要求创建文件时,NameNode会以块标识和该块的第一个副本的DataNodeIP地址作为响应。这个NameNode还会通知其他将要接收该块的副本的DataNode。NameNode在一个称为FsImage的文件中存储所有关于文件系统名称空间的信息。这个文件和一个包含所有事务的记录文件(这里是EditLog)将存储在NameNode的本地文件系统上。FsImage和EditLog文件也需要复制副本,以防文件损坏或NameNode系统丢失。2.3、DataNodeNameNode也是一个通常在HDFS实例中的单独机器上运行的软件。Hadoop集群包含一个NameNode和大量DataNode。DataNode通常以机架的形式组织,机架通过一个交换机将所有系统连接起来。Hadoop的一个假设是:机架内部节点之间的传输速度快于机架间节点的传输速度。萝卜网()DataNode响应来自HDFS客户机的读写请求。它们还响应创建、删除和复制来自NameNode的块的命令。NameNode依赖来自每个DataNode的定期心跳(heartbeat)消息。每条消息都包含一个块报告,NameNode可以根据这个报告验证块映射和其他文件系统元数据。如果DataNode不能发送心跳消息,NameNode将采取修复措施,重新复制在该节点上丢失的块。2.4、文件操作可见,HDFS并不是一个万能的文件系统。它的主要目的是支持以流的形式访问写入的大型文件。如果客户机想将文件写到HDFS上,首先需要将该文件缓存到本地的临时存储。如果缓存的数据大于所需的HDFS块大小,创建文件的请求将发送给NameNode。NameNode将以DataNode标识和目标块响应客户机。同时也通知将要保存文件块副本的DataNode。当客户机开始将临时文件发送给第一个DataNode时,将立即通过管道方式将块内容转发给副本DataNode。客户机也负责创建保存在相同HDFS名称空间中的校验和(checksum)文件。在最后的文件块发送之后,NameNode将文件创建提交到它的持久化元数据存储(在EditLog和FsImage文件)。2.5、Linux集群Hadoop框架可在单一的Linux平台上使用(开发和调试时),但是使用存放在机架上的商业服务器才能发挥它的力量。这些机架组成一个Hadoop集群。它通过集群拓扑知识决定如何在整个集群中分配作业和文件。Hadoop假定节点可能失败,因此采用本机方法处理单个计算机甚至所有机架的失败。三、Hadoop源代码分析萝卜网()Google的核心竞争技术是它的计算平台。它的云计算基础设施包括五个方面:GoogleCluster、Chubby、GFS、BigTable、MapReduce。很快,Apache上就出现了一个类似的解决方案,目前它们都属于Apache的Hadoop项目,对应的分别是:Chubby--ZooKeeper、GFS--HDFS、BigTable--HBase、MapReduce--Hadoop。目前,基于类似思想的开放源代码的项目还很多,如Facebook用于用户分析的Hive等。HDFS作为一个分布式文件系统,是所有这些项目的基础。分析好HDFS,有利于了解其他系统。Hadoop各个包之间的依赖关系比较复杂,原因是HDFS提供了一个分布式文件系统,该系统提供API,可以屏蔽本地文件系统和分布式文件系统的区别,甚至像AmazonS3这样的在线存储系统。这就造成了分布式文件系统的实现,或者是分布式文件系统的底层的实现,依赖于某些貌似高层的功能。功能的相互引用,造成了蜘蛛网型的依赖关系。一个典型的例子就是包conf,conf用于读取系统配置,它依赖于fs,主要是读取配置文件的时候,需要使用文件系统,而部分的文件系统的功能,在fs中被抽象了。3.1、org.apache.hadoop.io由于Hadoop的MapReduce和HDFS都有通信的需求,需要对通信的对象进行序列化。Hadoop并没有采用Java的序列化,而是引入了它自己的系统。org.apache.hadoop.io中定义了大量的可序列化对象,他们都实现了Writable接口。实现了Writable接口的一个典型例子如下:Java代码:萝卜网()1.publicclassMyWritableimplementsWritable{2.//Somedata3.privateintcounter;4.privatelongtimestamp;5.6.publicvoidwrite(DataOutputout)throwsIOException{7.out.writeInt(counter);8.out.writeLong(timestamp);9.}10.11.publicvoidreadFields(DataInputin)throwsIOException{12.counter=in.readInt();13.timestamp=in.readLong();14.}15.16.publicstaticMyWritableread(DataInputin)throwsIOException{17.MyWritablew=newMyWritable();萝卜网()18.w.readFields(in);19.returnw;20.}21.}其中的write和readFields分别实现了把对象序列化和反序列化的功能,是Writable接口定义的两个方法。图4给出了庞大的org.apache.hadoop.io中对象的关系。图4.org.apache.hadoop.io中对象的关系这里,我把ObjectWritable标为红色,是因为相对于其他对象,它有不同的地位。当我们讨论Hadoop的RPC时,我们会提到RPC上交换的信息,必须是Java的基本类型,String和Writable接口的实现类,以及元素为以上类型的数组。ObjectWritable对象保存了一个可以在RPC上传输的对象和对象的萝卜网()类型信息。这样,我们就有了一个万能的,可以用于客户端/服务器间传输的Writable对象。例如,我们要把上面例子中的对象作为RPC请求,需要根据MyWritable创建一个ObjectWritable,ObjectWritable往流里会写如下信息对象类名长度,对象类名,对象自己的串行化结果这样,到了对端,ObjectWritable可以根据对象类名创建对应的对象,并解串行。应该注意到,ObjectWritable依赖于WritableFactories,那存储了Writable子类对应的工厂。我们需要把MyWritable的工厂,保存在WritableFactories中(通过WritableFactories.setFactory)。3.2、org.apache.hadoop.rpc介绍完org.apache.hadoop.io以后,我们开始来分析org.apache.hadoop.rpc。RPC采用客户机/服务器模式,请求程序就是一个客户机,而服务提供程序就是一个服务器。当我们讨论HDFS的,通信可能发生在:Client-NameNode之间,其中NameNode是服务器;Client-DataNode之间,其中DataNode是服务器;DataNode-NameNode之间,其中NameNode是服务器;DataNode-DateNode之间,其中某一个DateNode是服务器,另一个是客户端。萝卜网()如果我们考虑Hadoop的Map/Reduce以后,这些系统间的通信就更复杂了。为了解决这些客户机/服务器之间的通信,Hadoop引入了一个RPC框架。该RPC框架利用Java的反射能力,避免了某些RPC解决方案中需要根据某种接口语言(如CORBA的IDL)生成存根和框架的问题。但是,该RPC框架要求调用的参数和返回结果必须是Java的基本类型,String和Writable接口的实现类,以
本文标题:Hadoop中HDFS的实现代码分析
链接地址:https://www.777doc.com/doc-6164372 .html