共计 1081 个字符,预计需要花费 3 分钟才能阅读完成。
之前也提过,客户端须要写数据的时候,就会跟 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 不是最初一个节点,那就会反复下面的操作。