背景:了解客户端及与之交互的HDFS,namenode,datanode之间的数据流是什么样的。
引用资料:《Hadoop权威指南》
如图:
读取流程:
- 客户端通过调用 FileSystem 对象的 open() 方法来打开希望读取的文件,对于 HDFS 来说,这个对象是 DistributedFileSystem 的一个实例。
- DistributedFileSystem 通过使用远程过程调用(RPC)来调用 namenode ,以确定文件起始块的位置。对于每一个块,namenode 返回存有改块副本的 datanode 地址。这些datanode 根据他们与客户端的距离来排序(根据集群的网络拓扑)。如果该客户端本身就是一个 datanode (比如,在一个 MapReduce 任务中),那么该客户端会从不保存有相应数据块副本的本地 datanode 读取数据。
- DistrubuteFileSystem 类返回一个 FSDataInputStream 对象(一个支持文件定位的输入流)给客户端以读取数据。FSDataInputStream 类转而封装 DFSInputStream 对象,改对象管理着 datanode 和 namenode 的 I/O。接着,客户端对这个输入流调用 read() 方法(步骤3)。存储者文件起始几个块的 datanode 地址的 DFSInputStream 随即连接距离最近的文件中第一个块所在的 datanode 。通过对数据流反复调用 read()方法,可以将数据从 datanode 传输到客户端(步骤4)。到达块的末端时,DFSInputStream 关闭与该datanode 的连接,然后寻找下一个块的嘴贱 datanode(步骤5)。
- 一旦客户端完成读取,就对 FSDataInputStream 调用 close()方法(步骤6)。
在读取数据的时候,如果DFSInputStream 在与 datanode 通信是遇到错误,回尝试从这个块的另外一个最邻近的 datanode 读取数据。它也记住那个故障 datanode ,以保证以后不会反复读取该节点上后续的块。DFSInputStream 也会通过校验和确认从 datanode 发来的数据是否完整。如果发现有损坏的块,DFSInputStream 会试图从其他 datanode 读取其副本,也会将被损坏的块通知给 namenode。
优点:
- 客户端可以直接连接到 datanode 检索数据
- namenode 只需要响应块位置的请求,无需响应数据请求。