HDFS的写数据流程涉及三个主体:客户端、NameNode、DataNodes。
在这里仅简单介绍流程,详细流程可以浏览源码。
①首先,客户端会创建一个DFS对象(DistributedFileSystem),向NameNode发送上传文件的请求。
②NameNode收到请求后先检查该请求的权限,然后再检查目录结构是否存在(关键是检查这两个,还有其他检查内容)。如果检查通过,NameNode响应给客户端说可以上传文件。
③客户端收到可以上传的响应后,立刻向NameNode发送消息请求上传第一个Block(0~128MB),并表示要求NameNode返回DataNode,即告诉客户端写在哪个DataNode上。
④NameNode收到Block的上传请求后,会先考虑DataNode的存在情况、节点距离最近、负载均衡等诸多因素,给客户端返回三个(根据策略不同也可以是N个)DataNode节点,表示让客户端在这三个节点存储数据。
⑤客户端收到三个节点后,开始创建流(FSDataOutputStream)。在创建流的过程中,会以chunk为最小单位(chunk:size < 512字节+4字节校验=516字节),建立多个chunk,组成一个packet(packet:size < 64KB),然后以此组成多个packet,以packet为单位准备发送上传数据。在创建packet的同时,还会建立一个ACK缓冲区,其中每个条目对应一条上传的数据,用来表示上传成功与否的情况。
⑥在发送前,还会向目标的一个DataNode1请求建立Block传输通道,DataNode1会联系DataNode2请求建立通道、DataNode2联系DataNode3请求建立通道。DataNode3->DataNode2->DataNode1->客户端依次应答。
⑦数据串行传输,DataNode1收到一个Packet后悔边向自己磁盘中写数据,边向DataNode2发送数据,依次来提高传输效率。每个Packet传输成功后都会通过链式的方式向前应答(DN3->DN2->DN1->Client),客户端收到应答后会移除ACK队列中对应刚刚上传的那个Packet的数据,以此来表示上传成功。若没有成功,ACK会再次将对应的数据塞到Packet里面,再次发送。最后关闭资源。
选择副本节点上面的步骤④中,NameNode会告诉Client把副本存到哪个节点上。在HDFS官方文档中,策略如下:如果客户端是集群中的一个节点,那么会在客户端自身的节点存一个副本,如果客户端在集群之外,那么会随机选择集群中任意一个机架中的任意一个节点。第二个副本则会选择另一个机架中的随机一个节点进行存储。第三个副本会在第二个副本所在的机架中再随机选择一个节点进行存储。第二三个副本选择一个机架的原因是为了提高效率,因为同一个机架传输效率更高。
节点距离节点距离计算方法:找两个节点最近的公共祖先,每一步距离唯一。
举个例子,节点A在集群1的机架3中,节点B在集群2的机架1中,两个集群在一个网络下。那么节点距离为4。节点A到机架3的交换机记距离1,机架3到集群1记距离1,节点B到机架1的交换机记距离1,机架1到集群2记距离1,1+1+1+1=4。
HDFS读数据流程HDFS的读数据流程也涉及三个主体:客户端、NameNode、DataNodes。
①首先,客户端会创建一个DFS对象(DistributedFileSystem),向NameNode发送下载指定文件的请求。
②NameNode收到请求后先检查该请求是否有下载该文件的权限,然后再检查目录结构是否存在(也就是检查元数据)。如果检查通过,NameNode返回给客户端目标文件的元数据。
③Client收到返回的元数据后,会创建一个FSDataInputStream流对象,然后向距离客户端节点距离最近的一个DataNode节点请求数据(block_part1),并考虑该节点的负载。如果该DataNode负载量较大,那么会向另一个DataNode发送请求。
④DataNode会将数据(block_part1)发送给Client,Client在等待block_part1传输成功后再发起block_part2的请求。在HDFS中,整个blocks下载的过程是串行的,而不是并行的。其中block的size最大为128MB。下载完毕后关闭资源。



