HDFS读写底层源码

一、HDFS 客户端读文件流程
HDFS读写底层源码_第1张图片
1、打开HDFS文件: HDFS客户端首先调用DistributedFileSystem.open方法打开HDFS文件,底层会调用ClientProtocal.open方法,返回一个用于读取的HdfsDataInputStream对象

2、从NameNode获取DataNode地址:在构造DFSInputStream的时候,对调用ClientPortocal.getBlockLocations方法向NameNode获取该文件起始位置数据块信息。NameNode返回的数据块的存储位置是按照与客户端距离远近排序的。所以DFSInputStream可以选择一个最优的DataNode节点,然后与这个节点建立数据连接读取数据块

3、连接到DataNode读取数据块: HDFS客户端通过调用DFSInputSttream从最优的DataNode读取数据块,数据会以数据包packet形式从DataNode以流式接口传送到客户端,当达到一个数据块末尾的时候,DFSInputStream就会再次调用ClientProtocal.getBlockLOctions获取下一个数据块的位置信息,并建立和这个新的数据块的最优节点之间的连接,然后HDFS继续读取数据块

4、客户端关闭输入流
注意:客户端读取数据块的时候,很有可能这个数据块的DataNode出现异常,也就是无法读取数据。这时候DFSInputStream会切换到另一个保存了这个数据块副本的DataNode,然后读取数据。另外,数据块的应答不仅包含了数据块还包含了校验值,HDFS客户端收到数据应答包的时候,会对数据进行校验,如果校验错误,也就是DataNode这个数据块副本出现了损坏,HDFS 客户端会通过ClientProtocal.reportBadBlocks向NameNode汇报这个损坏的数据块副本,同时DFSInputStream会尝试从其他DataNode读取这个数据块

二、HDFS 客户端写文件的流程
HDFS读写底层源码_第2张图片
简单的流程介绍:

1、HDFS 客户端调用DistributedFileSystem.create()方法

2、底层在调用ClientProtocal,create()方法在NameNode的文件系统目录树中创建一个文件,并且创建新文件的操作记录到editlog中,返回一个HdfsDataOutputStream对象,底层是对DFSOutputStream进行了一个包装。

3、HDFS 客户端根据返回的输出流对象调用write方法来写数据

4、由于之间创建的新文件是一个空文件,并没有申请任何数据块,所以DFSOutputStream首先会调用ClientProtocal.addBlock向NameNode

申请数据块,数据块的大小可以由用户自己配置,默认128M,NameNode返回一个LocatedBlock对象,这个对象保存了这个数据块所有DataNode位置信息,然后就可以建立数据流管道写数据块了

5、建立通向DataNode的数据流管道,写入数据:建立数据流管道之后,HDFS客户端就可以向数据流管道写数据。它会将数据切分成一个个的数据包packet,然后通过数据流管道发送到DataNode

6、每一个packet都有一个确认包,逆序的通过数据流管道回到输出流。输出流在确认了所有的DataNode已经写入了这个数据包,就会从对应的缓存队列删除这个数据包

7、当DataNode成功接收一个数据块时,DataNode会通过DataNodeProtocal.blockReceivedAndDelete方法向NameNode汇报,NameNode会更新内存中数据块和数据节点的对应关系

8、完成操作后,客户端关闭输出流

三、DataNode写文件的流程

HDFS客户端通过流式接口DataTransferProtocol的子类Sender调用writeBlock,向数据流管道写入数据。在写的时候会传入从NameNode查询到的可用DataNode的信息。

DataNode在启动的时候,会创建DataXceiverServer对象,并以后台方式运行,DataXceiverServer是一个线程类,它会一直判断DataNode是否运行正常,监听是否有请求进来;如果有新的请求进来,则构造一个流式接口DataTransferProtocol的子类Receiver子类:DataXceiver线程服务这个请求,并启动这个DataXceiver。

DataXceiver启动之后,会解析当前输入流中的操作,是读还是写等,我们这里是写操作,那么操作码就是:WRITE_BLOCK,然后根据解析的WRITE_BLOCK作为参数,针对不同的操作码调用Receiver不同的方法,比如这里就是opWriteBlock方法.

客户端会将数据块切分成不同的数据包packet,数据包首先发送到第一个DataNode节点,成功接收后,会将数据包写入磁盘,然后将数据包发送到数据流管道中的第二个DataNode节点,以此类推,到数据流管道最后一个也就是第三个DataNode,会对收到的数据包进行校验,校验成功,DataNode3会发送数据包确认消息,这个消息会逆向的通过数据流管道回到客户端。当一个数据块中所有数据包发送完毕,并且受到确认消息,客户端会发送一个空的数据包标识当前数据块已经发送完毕。

四、DataNode读文件过程

HDFS客户端发送Sender.readBlock之后,DataXceiverServer检测到有新的请求到来,监听是否有请求进来;如果有新的请求进来,则构造一个流式接口DataTransferProtocol的子类Receiver子类:DataXceiver线程服务这个请求,并启动这个DataXceiver。

DataXceiver启动之后会解析请求操作,并根据请求操作码调用具体的方法opReadBlock。

你可能感兴趣的:(大数据,Hadoop,hadoop,hdfs)