hadoop源码hdfs学习-基础知识

在HDFS中,Namenode是HDFS的Master节点,负责管理文件系统的命名空间(namespace),以及数据块到具体DataNode节点的映射信息,集群中的DataNode一般是一个节点一个,,负责他所在节点上的存储。从内部看,一个文件被分为多个数据块,存储在以组DataNode上,以本地文件的形式保存这些数据块以及数据块的校验信息。

用户能通过HDFS客户端发起读写HDFS文件的请求,执行文件系统的命名空间操作,比如打开、关闭、重命名文件或目录。NameNode会响应这些请求,更改命名空间以及数据块的映射信息,然后指导DataNode处理文件HDFS客户端的读写请求。

1 基本概念

1)数据块block    大部分 Linux 文件 系统( ext2、 ext3) 的 数据 块 概念 相同,

2)名字节点Namenode 名字节点保存文件系统的命名空间,包括文件系统目录树,文件/目录信息以及文件的数据块索引,两个文件保存,命名空间镜像文件和编辑日志文件。还保存数据块和数据节点的对应关系,这部分数据是名字节点启动时动态创建的。客户端通过名字节点获取上述信息,读写文件数据。支持HA。活动名字节点和备用名字节点。如果集群中文件数量过多时,名字节点的内存将成为限制系统横向扩展的瓶颈。为了解决这个问题,Hadoop2.X版本引入了联邦HDFS机制(HDFSFederation)。联邦HDFS机制允许添加名字节点以实现命名空间的扩展,其中每个名字节点都管理文件系统命名空间中的一部分,是一个独立的命名空间卷(namespacevolume)。命名空间卷之间是相互独立的,两两之间并不相互通信,甚至其中一个名字节点失效了也不会影响由其他名字节点维护的命名空间的可用性。例如,一个名字节点可能管理/user目录下的所有文件,而另一个名字节点可能管理/share目录下的所有文件,这两个名字节点独立运行,互不影响。

3)数据节点  不断向Namenode发送心跳信息、数据块汇报、缓存汇报,名字节点一心跳、数据库汇报、缓存汇报向数据节点发送指令,比如创建、删除、复制数据。

4)客户端  命令行接口、浏览器接口、代码API接口。建立在DFSClient类的基础上的,封装了客户端与HDFS其他节点间的交互。

5)通信协议

HDFS节点间的接口主要两种类型 ①Hadoop RPC接口:HDFS中基于Hadoop RPC框架实现的接口。②流式接口:HDFS中基于TCP或者HTTP实现的接口。

2    Hadoop rpc接口

HadoopRPC调用使得HDFS进程能够像本地调用一样调用另一个进程中的方法,并且可以传递Java基本类型或者自定义类作为参数,同时接收返回值。

底层基于Protobuf实现。定义在org.apache.hadoop.hdfs.protocol包和org.apache.hadoop.hdfs.server.protocol包

Clientprotocol 定义了客户端与Namenode间的接口。

ClientDataNodeProtocol:客户端与DataNode间的接口。获取数据节点信息。真正的数据读写交互是流式接口。

1)clientProtocol

■ HDFS文件读相关的操作。
■ HDFS文件写以及追加写的相关操作。
■ 管理HDFS命名空间(namespace)的相关操作。

上面三个接口可在FileSystem类中找到对应方法,实现Hadoop文件系统。
■ 系统问题与管理相关的操作。

DFSAdmin工具类,支持管理员配置和管理hdfs的。
■ 快照相关的操作。
■ 缓存相关的操作。
■ 其他操作。如安全,XAttr等方法。

①读数据相关方法

客户端会调用ClientProtocol.getBlockLocations()方法获取HDFS文件指定范围内所有数据块的位置信息。
publicLocatedBlocksgetBlockLocations(Stringsrc,longoffset,longlength)throwsAccessControlException,FileNotFoundException,UnresolvedLinkException,IOException;

客户端会调用ClientProtocol.reportBadBlocks()方法向Namenode汇报错误的数据块。
  public void reportBadBlocks(LocatedBlock[] blocks) throws IOException;
②写/追加写数据方法

ClientProtocol中定义了8个方法支持HDFS文件的写操作:create()、append()、addBlock()、complete()、abandonBlock()、getAddtionnaIDatanodes()、updateBlockForPipeline()和updatePipeline()。
 

create()方法用于在HDFS的文件系统目录树中创建一个新的空文件,创建的路径由src参数指定。这个空文件创建后对于其他的客户端是“可读”的,但是这些客户端不能删除、重命名或者移动这个文件,直到这个文件被关闭或者租约过期。客户端写一个新的文件时,会首先调用create()方法在文件系统目录树中创建一个空文件,然后调用addBlock()方法获取存储文件数据的数据块的位置信息,最后客户端就可以根据位置信息建立数据流管道,向数据节点写入数据了。
public HdfsFileStatus create(String src, FsPermission masked,
      String clientName, EnumSetWritable<CreateFlag> flag,
      boolean createParent, short replication, long blockSize, 
      CryptoProtocolVersion[] supportedVersions)
      throws AccessControlException, AlreadyBeingCreatedException,
      DSQuotaExceededException, FileAlreadyExistsException,
      FileNotFoundException, NSQuotaExceededException,
      ParentNotDirectoryException, SafeModeException, UnresolvedLinkException,
      SnapshotAccessControlException, IOException;

append()方法用于打开一个已有的文件,如果这个文件的最后一个数据块没有写满,则返回这个数据块的位置信息(使用LocatedBlock对象封装);如果这个文件的最后一个数据块正好写满,则创建一个新的数据块并添加到这个文件中,然后返回这个新添加的数据块的位置信息。客户端追加写一个已有文件时,会先调用append()方法获取最后一个可写数据块的位置信息,然后建立数据流管道,并向数据节点写入追加的数据。如果客户端将这个数据块写满,与create()
public LocatedBlock append(String src, String clientName)

客户端调用addBlock()方法向指定文件添加一个新的数据块,并获取存储这个数据块副本的所有数据节点的位置信息(使用LocatedBlock对象封装)。要特别注意的是,调用addBlock()方法时还要传入上一个数据块的引用。Namenode在分配新的数据块时,会顺便提交上一个数据块,这里previous参数就是上一个数据块的引用。excludeNodes参数则是数据节点的黑名单,保存了客户端无法连接的一些数据节点,建议Namenode在分配保存数据块副本的数据节点时不要考虑这些节点。favoredNodes参数则是客户端所希望的保存数据块副本的数据节点的列表。客户端调用addBlock()方法获取新的数据块的位置信息后,会建立到这些数据节点的数据流管道,并通过数据流管道将数据写入数据节点。

public LocatedBlock addBlock(String src, String clientName,ExtendedBlock previous, DatanodeInfo[] excludeNodes, long fileId,       String[] favoredNodes)

当客户端完成了整个文件的写入操作后,会调用complete()方法通知Namenode。这个操作会提交新写入HDFS文件的所有数据块,当这些数据块的副本数量满足系统配置的最小副本系数(默认值为1),也就是该文件的所有数据块至少有一个有效副本时,complete()方法会返回true,这时Namenode中文件的状态也会从构建中状态转换为正常状态;否则,complete()会返回false,客户端就需要重复调用complete()操作,直至该方法返回true。
  public boolean complete(String src, String clientName,
                          ExtendedBlock last, long fileId)
      throws AccessControlException, FileNotFoundException, SafeModeException,
      UnresolvedLinkException, IOException;

写异常接口

客户端调用abandonBlock()方法放弃一个新申请的数据块。考虑下面这种情况:当客户端获取了一个新申请的数据块,发现无法建立到存储这个数据块副本的某些数据节点的连接时,会调用abandonBlock()方法通知名字节点放弃这个数据块,之后客户端会再次调用addBlock()方法获取新的数据块,并在传入参数时将无法连接的数据节点放入excludeNodes参数列表中,以避免Namenode将数据块的副本分配到该节点上,造成客户端再次无法连接这个节点的情况。
public void abandonBlock(ExtendedBlock b, long fileId,
      String src, String holder)
      throws AccessControlException, FileNotFoundException,
      UnresolvedLinkException, IOException;

如果客户端已经成功建立了数据流管道,在客户端写某个数据块时,存储这个数据块副本的某个数据节点出现了错误该如何处理呢?客户端首先会调用getAdditionalDatanode()方法向Namenode申请一个新的Datanode来替代出现故障的Datanode。然后客户端会调用updateBlockForPipeline()方法向Namenode申请为这个数据块分配新的时间戳,这样故障节点上的没能写完整的数据块的时间戳就会过期,在后续的块汇报操作中会被删除。最后客户端就可以使用新的时间戳建立新的数据流管道,来执行对数据块的写操作了。数据流管道建立成功后,客户端还需要调用updatePipeline()方法更新Namenode中当前数据块的数据流管道信息。至此,一个完整的恢复操作结束。
 

在写数据的过程中,Client节点也有可能在任意时刻发生故障。对于任意一个Client打开的文件都需要Client定期调用ClientProtocol.renewLease()方法更新租约。如果Namenode长时间没有收到Client的租约更新消息,就会认为Client发生故障,这时就会触发一次租约恢复操作,关闭文件并且同步所有数据节点上这个文件数据块的状态,确保HDFS系统中这个文件是正确且一致保存的。

写操作时,Namenode故障的HA处理后面再说

3 命名空间管理

4   系统 问题 与 管理 操作

DFSAdmin是供HDFS管理员管理HDFS集群的命令行工具。

一个典型的dfsadmin命令如下所示,管理员可以添加不同的参数以触发HDFS进行相应的操作。

hdfs dfsadmin [参数]

安全模式中的Namenode不接受客户端对命名空间的修改操作,整个命名空间都处于只读状态。同时,Namenode也不会向Datanode下发任何数据块的复制、删除指令。管理员可以通过dfsadminsetSafemode命令触发Namenode进入或者退出安全模式,同时还可以使用这个命令查询安全模式的状态。需要注意的是,刚刚启动的Namenode会直接自动进入安全模式,当Namenode中保存的满足最小副本系数的数据块达到一定的比例时,Namenode会自动退出安全模式。而对于用户通过dfsAdmin方式触发Namenode进入安全模式的情况,则只能由管理员手动关闭安全模式,Namenode不可以自动退出。

  public boolean setSafeMode(HdfsConstants.SafeModeAction action, boolean isChecked) throws IOException;

refreshNodes()方法触发Namenode刷新数据节点列表,管理员可以通过Include文件制定可以连接到NameNode的数据节点列表,

覅哪里则Upgrade()和rollingUpgrade()都是与Namenode升级相关的

5 快照相关功能

6 缓存相关操作

二   clientDataNodeProtocol

定义了Client与DataNode之间的接口

猜你喜欢

转载自blog.csdn.net/strideahead/article/details/81108357
今日推荐