1、HDFS写流程
(1)客户端通过对FileSystem.create() 对象创建建文件,DistributedFileSystem会创建输出流FSDataOutputStream。
(2)DistributedFileSystem 通过RPC远程调用名称节点,在文件系统的命名空间中创建一个新的文件,此时该文件中还没有相应的数据块。
(3)名称节会执行一些检查,比如文件是否已经存在、客户端是都有权限创建文件等。检查通过后,名称节点会构造一个新文件,并添加文件信息。如果检查不通过,文件创建失败会向客户端抛一个 IOException 异常。
(4)DistributedFileSystem利用DFSDataOutputStream来实例化FSDataOutputStream,返回给客户端,客户端使用这个输出流写入数据(new DFSDataOutputStream)。
了解:DFSDataOutputStream负责处理 DataNode 和 NameNode 之间的通信
(5)客户端向输出流FSDataOutputStream中写入的数据会被分成一个个的分包,这些分包被放入DFSOutputStream对象的内部队列“dataQueue”
了解:
1)启动线程DataStreamer,它存储dataQueue.wait队列阻塞等待接收读取到的数据。
数据:packet(64k)= chunk(512byte)+ chunksum (4byte)。chunk:数据校验的基本单位。
每个chunk需要带有4Byte的校验位,127个形成一个packet 。(队列有了数据之后,要往外写数据)
因此,DataStreamer [ 获取block(机架感知)],去处理数据队列,挑选出适合存储数据副本的一
组 DataNode ,并要求 NameNode 分配新的数据块。
2)DataStreamer获取到数据节点 后,使用Socket请求发送packet
助记:FSDataOutputStream里有DFSDataOutputStream里有DataStreamer
(6)输出流FSDataOutputStream会向名称节点申请保存文件和副本数据块的若干个数据节点,这些数据节点(DataNode)形成一个数据流管道(Pipeline)。队列中的分包最后被打包成数据包,发往数据流管道的第一个数据节点, 第一个数据节点将数据包发送给第二个节点,第二个数据节点发送给第三个数据节点,数据包流经管道上个各个数据节点(即流水线复制策略)
了解:流水线(PipeLine),简单地理解就是客户端向DataNode传输数据(Packet)和接收DataNode
回复(ACK)的数据通路。整条流水线由若干个DataNode串联而成,数据由客户端流向PipeLine,
在流水线上,假如DataNode A 比 DataNode B 更接近流水线
流水线复制策略(扩充)
每个块都向HDFS集群中的名称节点发起写请求,名称节点会根据系统的各个数据节点的使用情况,
选择一个数据节点列表返回给客户端,然后客户端就把数据首先写入列表中的第一个数据节点,同
时把列表传给第一个数据节点,,当第一个数据节点接收到4KB数据的时候,写入本地,并且向第
二个数据节点发起连接请求,把自己已经接受到4KB数据和列表传给第二个数据节点,当第二个数
据节点接收到4KB数据的时候,写入本地,并且向列表中的第三个数据节点发起连接情节,以此类
推,列表中的多个数据节点形成一条数据复制的流水线。最后,当文件写完的时候,数据复制也同
时完成。
(7)【因为各个数据节点位于不同的机器,数据需要通过网络发送。为了保证所有数据节点的数据都是准确的,接收到数据的数据节点要向发送这发送"确认包"(ACK Packet)。】
确认包沿着数据流管道逆流而上,从数据流管道一次经过各个数据节点并最终发往客户端(DataStreamer),客户端收到应答时,它将u四月那个的分包从内部队列移除。不断执行(4)~(7)步,直到数据全部写完。
(8)客户端调用close()方法关闭输出流。
了解:此时,客户端不会再向输出流中写入数据,所有,当DFSOutputStream对象内部队列中的分包都收到应答后,就可以使用ClientProtocal.complete()方法通知名称节点关闭文件,完成一次正常的写文件的过程。