数据读取流程:

  1. 客户端访问NameNode,告知需要读取的文件

  2. 客户身份确认

    1. 通过信任的客户端。由其指定用户名

    2. 通过诸如kerberos等强制认证机制完成

  3. 检查文件的所有者及其设定的访问权限,如果文件确实存在,而且用户对这个有访问权限。NameNode告知客户端文件的第一个数据块的标号以及保存该数据块的DataNode列表(列表是根据DataNode与客户端间的距离排序的,距离是根据Hadoop集群的机架拓扑结构计算得到的)

  4. 客户端根据数据块标号和DataNode主机名,访问最合适的DataNode,读取所需要的数据块,直到所有数据块读取完成或客户端主动关闭了文件流


异常情况:

  1. 从DataNode读取数据时,进程或主机异常。此时读操作不会停止,HDFS库会自动尝试从其他有数据副本的DataNode中读取数据。如果所有数据副本都无法访问,则读取操作失败,客户端收到异常出错消息

  2. 当客户端试图从DataNode中读取数据时,NameNode返回的数据块位置信息已过期。这时若还有其他DataNode保存该数据块副本,则客户端会尝试从那些DataNode中读取数据,否则至此读取操作会失败


数据写入流程:

  1. 客户端通过hadoop文件系统相关api发送请求打开一个要写入的文件,若该用户有足够的权限,请求送抵NameNode,在NameNode上建立该文件的元数据

  2. 客户端收到“打开文件成功”的响应

  3. 客户端将数据写入流,数据会自动拆分成数据包,并将数据包保存在内存队列中

  4. 客户端的独立线程从队列中读取数据包,同时向NameNode请求一组DataNode列表,以便写入数据块的多个副本

  5. 客户端直接连接列表中的第一个DataNode,该DataNode又连接到第二个DataNode,第二个又连接第三个,建立数据块的复制管道

  6. 数据包以流的方式写入第一个DataNode的磁盘,同时传入管道中的下一个DataNode并写入其磁盘,以此类推

  7. 复制管道中的每个DataNode都会确认所收到数据包已成功写入磁盘

  8. 客户端维护一张列表,记录哪些数据包尚未收到确认消息,每收到一个响应,客户端便知道数据已成功写入到管道中的一个DataNode

  9. 当数据块被写满时,客户端将重新向NameNode申请下一组DataNode

  10. 客户端将剩余数据包全部写入磁盘,关闭数据流并通知NameNode文件写操作已完成


异常情况:

复制管道中的某一个DataNode无法将数据写入磁盘,管道立即关闭。已发送的但尚未收到确认的数据包会被回退到队列中,以确保管道中错误节点的下游节点可以获得数据包。在剩下的健康数据节点中,正在写入的数据块被分配新的ID。当发生故障的数据节点恢复后,冗余的数据块貌似不属于任何文件而自动丢弃,由剩余节点组成的新复制管道会重新开放,继续写操作直至文件关闭