HDFS的的写过程
1、HDFS写数据流程
- 客户端通过Distributed FileSystem模块向NameNode请求上传文件。NameNode检查权限、文件是否存在以及父目录是否存在;
- NameNode相应客户端是否可以上传;
- 客户端将数据按块大小切分,并向NameNode请求第一个Block上传的节点位置;
- NameNode返回节点位置(假设为dn1,dn2,dn3);
- 客户端通过FSDataOutputStream模块请求dn1上传数据,dn1收到请求会继续调用dn2,然后dn2调用dn3,将这个通信管道建立完成;
- dn1、dn2、dn3逐级应答客户端;
- 客户端开始往dn1上传第一个Block(先从磁盘读取数据放到一个本地内存缓存),以Packet为单位,dn1收到一个Packet就会传给dn2,dn2传给dn3;dn1每传一个packet会放入一个应答队列等待应答。
- 当一个Block传输完成之后,客户端再次请求NameNode上传第二个Block的服务器。(重复执行3-7步)。
2、DFSOutputStream内部原理
1、创建Packet
Client写数据时,会将字节流数据缓存到内部的缓冲区中,当长度满足一个Chunk大小(512B)时,便会创建一个Packet对象,然后向该Packet对象中写Chunk的Checksum校验和数据,以及实际数据块Chunk Data,校验和数据是基于实际数据块计算得到的。每次满足一个Chunk大小时,都会向Packet中写上述数据内容,直到达到一个Packet对象大小(64K),就会将该Packet对象放入到dataQueue队列(待发送数据包)中,等待DataStreamer线程取出并发送到DataNode节点。
2、发送Packet
DataStreamer线程从dataQueue队列中取出Packet对象,放到ackQueue队列(正在发送的队列)中,然后向DataNode节点发送这个Packet对象所对应的数据
3、接收ack
发送一个Packet数据包以后,会有一个用来接收ack的ResponseProcessor线程,如果收到成功的ack,则表示一个Packet发送成功,ResponseProcessor线程会将ackQueue队列中对应的Packet删除,在发送过程中;
如果发生错误,所有未完成的Packet都会从ackQueue队列中移除掉,然后重新创建一个新的Pipeline,排除掉出错的那些DataNode节点,接着DataStreamer线程继续从dataQueue队列中发送Packet。
只要有一个DN节点收到了数据,DN上报NN已经收完此块,NN就认为当前块已经传输成功!
NN会自动维护副本数!
源码中的注释:
/*
* When a client application fills up the currentPacket, it is
* enqueued into dataQueue. The DataStreamer thread picks up
* packets from the dataQueue, sends it to the first datanode in
* the pipeline and moves it from the dataQueue to the ackQueue.
* The ResponseProcessor receives acks from the datanodes. When an
* successful ack for a packet is received from all datanodes, the
* ResponseProcessor removes the corresponding packet from the
* ackQueue.
*
* In case of error, all outstanding packets and moved from
* ackQueue. A new pipeline is setup by eliminating the bad
* datanode from the original pipeline. The DataStreamer now
* starts sending packets from the dataQueue.
*/
3、网络拓扑-节点距离计算
节点距离:两个节点到达最近的共同祖先的距离总和。
4、机架感知
HDFS的的读过程
- 客户端通过DistributedFileSystem向NameNode请求下载文件,NameNode通过查询元数据,找到文件块所在的DataNode地址。
- 挑选一台DataNode(就近原则,然后随机)服务器,请求读取数据。
- DataNode开始传输数据给客户端(从磁盘里面读取数据输入流,以Packet为单位来做校验)。
- 客户端以Packet为单位接收,先在本地缓存,然后写入目标文件。
参考文献:
https://blog.csdn.net/weixin_45800556/article/details/102882932
https://www.cnblogs.com/feiyumo/p/12541296.html?ivk_sa=1024320u
https://blog.csdn.net/lslslslslss/article/details/121864556?spm=1001.2014.3001.5501