取原理
HDFS 读取原理比较简单,参考上面的例子,假如 HDFS 客户端现在想要读取“example.txt“。
现在,读取数据将发生以下步骤:
客户端将与 NameNode 联系,询问文件”example.txt“的 block 元数据;
NameNode 返回存储的每个块(block A 和 block B)的 DataNode 列表;
然后,客户端将连接到列表中最近的 DataNode;
客户端开始从 DataNode 并行读取数据(DN 1 的 block A 和 DN 3 的 block B)
一旦客户端获得了所有必须的 block,它就会将这些 block 组合起来形成一个文件。
在提供给客户端读取请求时,HDFS 选择最接近客户端的副本,这减少了读取延迟和带宽消耗。因此,如果可能,会选择与阅读节点位于同一个机架上的副本。
9. 数据读取实现
读取数据的详细流程:
1) 客户端通过调用 FileSystem 对象的 open() 方法来打开它希望读取的文件,其实就是创建了一个 DistributedFileSystem 对象(步骤1);
2) DistributedFileSystem 使用 RPC 调用 NameNode 来确定文件中前几个 block 的位置,同时对于每个 block,NameNode 返回具有该 block 副本的 DataNode 的地址,此外,DataNode 根据它们与客户端的接近程度进行排序(根据集群网络的拓扑结构),如果客户端本身就是一个 DataNode,那么它将从本地直接读取(步骤2)。
3) DistributedFileSystem 返回一个 FSDataInputStream(支持文件搜索的输入流)给客户端,供其从中读取数据;
4) FSDataInputStream 依次包装一个 DFSInputStream,它们用于管理 DataNode 和 NameNode 的 I/O 读写;
5) 客户端调用 stream 上的 read() 方法(步骤3);
6) DFSInputStream 中存储了文件中前几个 block 所在 DataNode 的地址,根据这些信息连接到文件中离 block 的最近的DataNode。数据从 DataNode 返回至客户端,客户端在数据流上重复调用 read() 方法(不同 block 并行读取)(步骤4,5);
7) 当 block 全部传输完成后,DFSInputStream 将关闭与 DataNode 的连接;
8) 当客户端完成数据读取后,调用 FSDataInputStream 上 close() 方法以关闭流(步骤6);
心跳检测、block 状态报告与数据重新复制
文件以 block 形式写入 DataNode 后,其副本数必须满足系统配置的数量(dfs.replication),即使是在之后 DataNode 发生了故障,比如磁盘错误或者宕机,HDFS 都应该有能力来处理这样的情况。所以这里就涉及到了几个问题:
1) HDFS 如果确定 Datanode 的状态
2) 如何确定哪些 block 出现了丢失
3) Datanode 发生故障后,如何保障数据的安全
在 HDFS 中,Datanode 以及 block 的元信息都通过 Namenode 来管理。Namenode 会周期性地从集群中的每个 Datanode 接收心跳信号和 block 状态报告(Blockreport)。接收到心跳信号意味着该 Datanode 节点工作正常,而 block 状态报告则包含了一个该 Datanode 上所有 block 的列表。
那么根据心跳信号以及 block 状态报告,Namenode 可以知道每一个 Datanode 是否正常工作,以及哪些 block 被损坏了。如果一个 Datanode 宕机了,那么任何存储在它之上的所有 block 将不再有效。Namenode 不断地检测这些 block 是否满足副本系数,一旦发现某个 block 的副本系数低于指定值,就会启动复制操作。可能需要重新复制的操作有:某个 Datanode 节点失效、某个副本遭到破坏、Datanode 上的磁盘错误、或者文件的副本系数变大。
10. 存储空间回收
文件的删除和恢复
当用户或应用程序删除某个文件时,这个文件并没有立刻从 HDFS 中删除。实际上 HDFS 会将这个文件重命名并转移到 /trash 目录,所以只要该文件在 /trash 目录中,就可以被迅速恢复。文件在 /trash 中保存的时间通过 fs.trash.interval 配置,当超过这个时间时,Namenode 就会将文件从 namespace 中删除。删除文件会使得该文件的 block 被释放。
Namenode 在做类似的常规扫描时,Namenode 找点孤儿 block(不被任何文件包含的 block)并删除它们的元数据。然后 Datanode 在和 Namenode 交互心跳信息中,报告它所拥有的 block 子集的信息,Namenode 回复 Datanode 哪些 block 在元数据中已经不存在了,Datanode 便可以任意删除这些 block 副本了。
减少副本系数
同样的,当一个文件的副本系数被减小后,Namenode 会选择过剩的副本删除。其原理与上面的类似。
作者:Alukar
链接:https://www.jianshu.com/p/77a5065be650
共同学习,写下你的评论
评论加载中...
作者其他优质文章