HDFS 读取过程
过程
- 客户端或者用户通过调用 FileSystem 对象的 open()方法打开需要读取的文件,这对 HDFS 来说是常见一个分布式文件系统的一个读取实例。
- FileSystem 通过远程协议调用 NameNode 确定文件的前几个 Block 的位置。对于每一个 Block, NameNode 返回一含有那个 Block 拷贝的“元数据”,即文件基本信息;接下来,DataNode 按照上文定义的距离值进行排序,如果 Client 本身就是一个 DataNode,那么优先从本地 DataNode 节点读取数据。 HDFS 实例做完以上工作后,返回一个 FSDataInputStream给客户端,让其从 FSDataInputStream 中读取数据。 FSDataInputStream 接着包装一个DFSInputStream,用来管理 DataNode 和 NameNode 的 I/O。
- NameNode 向客户端返回一个包含数据信息的地址,客户端根据地址创建一个FSDataInputStream 开始对数据进行读取。
- FSDataInputStream 根据开始时存放的前几个 Blocks 的 DataNode 的地址,连接到最近的 DataNode 上对数据开始从头读取。客户端反复调用 read()方法,以流式方式从DataNode 读取数据。
- 当读到 Block 的结尾的时候, FSDataInputStream 会关闭到当前 DataNode 的链接,然后查找能够读取下一个 Block 的最好的 DataNode。这些操作对客户端是透明的,客户端感觉到的是连续的流,也就说读取的时候就开始查找下一个块所在的地址。
- 读取完成调用 close()方法,关闭 FSDataInputStream。
以上就是 HDFS 对数据进行读取的整个流程。
错误处理
对于错误处理来说,在读取期间,当 Client 与 DataNode 通信的时候如果发生错误的话,它会尝试读取下个紧接着的含有那个 Block 的 DataNode。 Client 会记住发生错误的 DataNode,这样它就不必在读取以后的块的时候再尝试这个 DataNode 了。 Client 也验证从 DataNode 传递过来的数据的 checksum。如果错误的 Block 被发现,它将尝试从另一个 DataNode 读取数据前被报告给 NameNode。
ps:NameNode 中存放的是元数据,即将数据类型、大小、格式以对象的形式存放在 NameNode 内存中。便于加快读取速度。