HDFS写操作的整体流程概述

向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报告添加;
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值