总体流程:
1、客户端通过Distributed FileSystem 模块的create()方法向NameNode请求上传文件,并告诉namenode上传文件的文件名、文件大小、文件拥有者,NameNode检查目标文件是否已存在,父目录是否存在;
2、NameNode 返回是否可以上传;
3、客户端请求我的第一个 Block 上传到哪几个 DataNode 服务器上;
4、NameNode 返回 3 个 DataNode 节点,分别为 dn1、dn2、dn3(每个文件块默认存储在三个DN副本上,分别是本地结点、同一个机架上的不同结点以及不同机架的任意一个结点);
5、客户端通过 FSDataOutputStream 模块的write()方法请求 dn1 上传数据,dn1 收到请求会继续调用 dn2,然后 dn2 调用 dn3,将这个通信管道建立完成。(注意:并不是由客户端分别往3个datanode上写3份,而是dn1开启额外线程去调用dn2,dn2去调用dn3);
6、dn1、dn2、dn3 逐级应答客户端;
7、客户端以 Packet 为单位,以chunk为检验,开始往 dn1 上传第一个 Block(先从磁盘读取数据放到一个本地内存缓存),dn1 收到一个 Packet 就会传给 dn2,dn2 传给 dn3;dn1 每传一个 packet 会放入一个应答队列等待应答;
8、当一个 Block 传输完成之后,客户端再次请求 NameNode 上传第二个 Block 的服务器。(重复执行 3-7 步)。
注意:客户端在接收到NameNode返回的三个结点后,形成FSDataOutputStream数据流,这些数据流是一个一个的小的chunk(515byte + 4byte校验位),然后一个个小的chunk组成达到64k后,形成一个Packet,向DN中传输数据的单位是一个个的Packet。
核心问题:
1.传输blk1的过程中,dn3如果死了,集群会怎么处理?
不做任何处理,错误会向NN报告
2.接1,如果dn3又启动了,集群会如何处理?
dn3启动时,会向NN发送块报告,然后NN指示dn3删除blk1(因为传输数据不完整)
3.客户端建立通道时,发现dn3连接不上,会怎么办?
NN会重新分配三个节点
4.传输过程中,packet出错,会如何处理?
会重新上传,但是重传次数只有4次,超过限制则提示传输失败
5.如果bk1上传成功,blk2坏了,或者blk2上传时,dn1挂了,如何处理?
NN将整个文件标记为无效,下次dn向NN发送块报告时,NN会通知这些块所在的节点删除
6.在 HDFS 写数据的过程中,NameNode 会选择距离待上传数据最近距离的 DataNode 接收数据。那么这个最近距离怎么计算呢?
节点距离:两个节点到达最近的共同祖先的距离总和。
总体流程:
(1)客户端通过 DistributedFileSystem 向 NameNode 请求下载文件,NameNode 通过查询元数据,检测数据是否存在,若存在,则找到文件块所在的 DataNode 地址,给客户端响应。
(2)挑选一台 DataNode(就近原则,然后随机)服务器,请求读取数据。
(3)DataNode 开始传输数据给客户端(从磁盘里面读取数据到输入流,以 Packet 为单位来做校验)。
(4)客户端以 Packet 为单位接收,先在本地缓存,然后写入目标文件。
注意:1、在根据就近原则挑选到DataNode1之后,不能所有的客户端都选择DataNode1开始传输,除了考虑传输速率外,还要考虑服务器的负载均衡,当DataNode1 达到负载均衡后,就开始请求DataNode2 传输数据。
2、客户端在和DN建立传输通道时不是级联方式,而是串行读数据的,首先寻找离自己最近的副本(dn1)下载,如果数据不完整或者没有找到,就再向dn2建立传输通道,然后传输数据,依次往下,直到下载到目标文件为止。读完Block1之后,读块Block2。
注:本文参考尚硅谷Hadoop教学。