之前也提过,客户端须要写数据的时候,就会跟NameNode说他筹备把文件上传到某个目录,NameNode就会开始进行元数据的更新。因为元数据的更新是十分重要的,所以客户端会在肯定条件内重试,直至胜利。

元数据更新胜利后,Client就会创立两个队列,一个是dataQueue,一个是ackQueue。这两个队列的作用下文会讲。

客户端写入的时候,是一个个chunk写的,每一个chunk的大小是512byte,chunk的校验和chunksum是4byte,这个校验和是对块的内容进行校验用的,所以每写入一个chunk的大小就是516byte。

这些chunk写满后,就会寄存在一个叫做packet的东东外面,这个packet有64k的大小,所以就是65535byte,相当于127个chunk。每次写满一个packet或者写满128M(就是block的大小),就会创立一个新的packet给chunk写入。

曾经写满的packet,就是放在下面提到的dataQueue。

客户端有其余线程,会监控dataQueue,此时他发现了dataQueue有数据了,他就开始向NameNode申请block信息。
NameNode会依据负载平衡以及机架感知,把计算后的DataNode的信息给到客户端。

失去DataNode信息后的客户端,就开始与其中一个DataNode建设数据管道,这个DataNode又会与其余DataNode建设数据管道。

建设数据管道的作用,就是把通过socket把数据传过来,客户端这里并没有间接和三个DataNode建设数据管道,这是因为DataNode个别是同一个机房的,所以他们外部通信的速度会比拟快。
管道建设胜利后,客户端就会把dataQueue队列的头部packet拿进去,通过socket传给DataNode,另外也会把packet放入到ackQueue。

放入ackQueue的起因是为了避免packet传输给DataNode失败,如果失败了,就会把packet队列的packet放回到dataQueue,这样监听dataQueue队列的线程就会从新把她拿进去进行传输。如果传输胜利了,会把ackQueue的packet移除。
DataNode接管到数据后,会把数据写入ackQueue队列,而后再把packet传输给上游,最初才写入磁盘。

这个ackQueue队列的作用跟下面一样,是为了避免传输失败,如果传输胜利,就会把ackQueue队列中的packet移除,如果失败,就会持续传输。
如果DataNode不是最初一个节点,那就会反复下面的操作。