HDFS 写入流程
过程
- Client 通过调用 FileSystem 的 create()方法来请求创建文件
- FileSystem 通过对 NameNode 发出远程请求,在 NameNode 里面创建一个新的文件,但此时并不关联任何的块。 NameNode 进行很多检查来保证不存在要创建的文件已经存在于文件系统中,同时检查是否有相应的权限来创建文件。如果这些检查都完成了,那么NameNode 将记录下来这个新文件的信息。 FileSystem 返回一个 FSDataOutputStream 给客户端用来写入数据。和读的情形一样, FSDataOutputStream 将包装一个 DFSOutputStream 用于和 DataNode 及 NameNode 通信。而一旦文件创建失败,客户端会收到一个 IOExpection,标示文件创建失败,停止后续任务。
- 客户端开始写数据。 FSDataOutputStream 把要写入的数据分成包的形式,将其写入到中间队列中。其中的数据由 DataStreamer 来读取。 DataStreamer 的职责是让 NameNode分配新的块——通过找出合适的 DataNode——来存储作为备份而复制的数据。这些DataNode 组成一个流水线,我们假设这个流水线是个三级流水线,那么里面将含有三个节点。此时, DataStreamer 将数据首先写入到流水线中的第一个节点。此后由第一个节点将数据包传送并写入到第二个节点,然后第二个将数据包传送并写入到第三个节点。
- FSDataOutputStream 维护了一个内部关于 packets 的队列,里面存放等待被DataNode 确认无误的 packets 的信息。这个队列称为等待队列。一个 packet 的信息被移出本队列当且仅当 packet 被流水线中的所有节点都确认无误
- 当完成数据写入之后客户端调用流的 close 方法,在通知 NameNode 完成写入之前,这个方法将 flush 残留的 packets,并等待确认信息( acknowledgement)。 NameNode 已经知道文件由哪些块组成(通过 DataStream 询问数据块的分配),所以它在返回成功前只需要等待数据块进行最小值复制。
错误处理
关于写入数据的时候 DataNode 发生错误的处理过程如下:发现错误之后,首先关闭流水线,然后将没有被确认的数据放到数据队列的开头,当前的块被赋予一个新的标识,这信息将发给 NameNode,以便在损坏的数据节点恢复之后删除这个没有被完成的块。然后从流水线中移除损坏的 DataNode。之后将这个块剩下的数据写入到剩下的两个节点中。NameNode 注意到这个块的信息还没有被复制完成,他就在其他一个 DataNode 上安排复制。接下来的 Block 写入操作就和往常一样了。