您的位置:首页 > 大数据 > Hadoop

HDFS写操作的整体流程概述

2013-11-03 13:43 281 查看
向HDFS写入文件的操作流程图如下:



根据上图对整个写操作的逻辑进行讲解:

1.调用DistributedFileSystem.create(....)方法,在此方法中初始化DFSClient.DFSOutputStream对象并以此对象为参数初始化FSDataOutputStream对象然后返回FSDataOutputStream对象给客户端;

2.在初始化DFSClient.DFSOutputStream对象时,调用了NameNode.create(....)方法,根据path路径在FSDirectory.rootDir目录树结构中创建一个叶子节点INodeFileUnderConstruction对象;

3.客户端调用FSDataOutputStream.write(byte b[], int off, int len)方法

3.1)将文件内容封装成Packet添加到DFSOutputStream.dataQueue队列中;

3.2)DFSClient.DFSOutputStream.DataStreamer线程监听DFSOutputStream.dataQueue队列,处理队列中的packet数据包;

3.2.1)新建Block块信息,添加到path在目录树结构中叶子节点INodeFileUnderConstruction对象的BlockInfo[]中;添加到FSNamesystem.blocksMap中

3.2.2)查找replication个目标DataNode封装成DatanodeDescriptor[]数组;并将获得的DatanodeDescriptor[]数组set到INodeFileUnderConstruction.targets中;

3.2.3)返回以新建的Block和查找到的目标DataNode信息列表来初始化LocatedBlock对象;

3.2.4)与DatanodeDescriptor[]数组中的第一个DataNode创建数据输出流(用于写入文件内容)和数据输入流(用于获取回执消息);

3.2.5)向数据输出流中写入消息头,包括:DATA_TRANSFER_VERSION,DataTransferProtocol.OP_WRITE_BLOCK,blockid,GenerationStamp,剩下的DatanodeDescriptor[]数组个数以及剩下的每个数组元素DatanodeInfo的信息(包括ipport,大小,使用率,剩余大小,最后更新时间,位置,hostname等),检验和字节数组,传递剩下的DataNodeInfo信息主要是DataNode将block文件复制到其他DataNode时使用;

3.2.6)将文件内容写入数据输出流;

4.DataNode端在启动的时候就启动了线程DataXceiverServer专门监听客户端或其他DataNode到来的请求链接,由DataXceiver线程负责处理请求;收到第3.2.5和3.2.6步传来的请求消息后,DataXceiver线程调用DataXceiver.writeBlock(DataInputStream in)完成文件的写入;

4.1)从输入流解析blockid,GenerationStamp信息,并用于初始化Block对象:block;

4.2)DataNode可以配置多个存放文件的路径,每个路径对应一个FSVolume对象,选择一个有足够大可用空间的FSVolume,即选择了一个存放文件的路径;

4.3)当是从客户端传来的写入文件请求,则在选择的${dfs.data.dir}路径下的tmp目录下面创建blk_blockid文件;当是从其他DataNode传来的则选择的${dfs.data.dir}路径下的blocksBeingWritten目录下面创建blk_blockid文件;

4.4)将Block对象添加到FSDataset.volumeMap中;

4.5)此DataNode暂时作为客户端,按照3.2.4-3.2.6步的处理逻辑将文件内容复制到剩余的DataNode上;后续剩下的DataNode也按此逻辑处理;

4.6)将文件内容写入此DataNode的磁盘中;

5.当此DataNode下一个DataNode的确认消息之后,将${dfs.data.dir}/tmp或${dfs.data.dir}/blocksBeingWritten目录下面的文件移植到${dfs.data.dir}/current目录中;依次确认并处理,直到第一个DataNode也收到确认消息后通知客户端;

6.客户端调用FSDataOutputStream.close()方法,关闭所有的数据输出流和输出流,并调用NameNode.complete(String src, String clientName)方法,通知NameNode文件写入操作完成;

7.第6步触发调用NameNode.complete(String src, String clientName)方法,将path路径在目录树结构中的叶子节点INodeFileUnderConstruction对象转变成INodeFile对象;其中INodeFile.BlockInfo[]数组变量中的每个BlockInfo元素的三元组Object[]的DataNode数据由DataNode线程定期调用的NameNode.blockReceived(DatanodeRegistration nodeReg, Block[]
blocks, String[] delHints)方法向NameNode报告添加;
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: