您的位置:首页 > 大数据 > Hadoop

HDFS文件读取详解

2015-08-02 19:14 260 查看
客户端与HDFS文件读取
  创建HDFS文件系统实例
    FileSystem fs = FileSystem.get(new URI("hdfs://ns1"), new Configuration(),"root");
  客户端通过调用FileSystem对象fs的Open()方法打开要读取的文件,DistributedFileSystem通过使用RPC来调用NameNode,以确定文件起始块的位置。
  对于文件的每一个块,NameNode返回存有该块副本的DataNode地址。这些DataNode根据它们与客户端的距离来排序(根据集群中的网络拓扑)。如
  果该客户端本身就是一个DataNode(例如在一个MapReduce任务中)并保存有相应数据块的一个副本时,该节点就会从本地DataNode读取数据。然后
  DistributedFileSystem返回一个FSDataInputStream对象(支持文件定位的输入流)给客户端读取数据。FSDataInputStream类转而封装DFSInputStream
  对象,该对象管理着DataNode和NameNode的I/O。
    FSDataInputStream in = fs.open(new Path(dfsPath));
  接着客户端对这个输入流调用read()方法读取,存储着文件起始位置的几个块的DataNode地址的DFSInputStream随机链接距离最近的DataNode。通过
  对数据流反复调用read()方法,将数据从DataNode传输到客户端,到达快的末端时,DFSInputStream关闭与该DataNode的连接,然后寻找下一个块的
  最佳DataNode,客户端只需要读取连续的流。客户端从流中读取数据时,块是按照打开DFSInputStream与DataNode新建连接顺序的读取的,它也会根
  据需要询问NameNode来检索下一批数据块的DataNode的位置,一旦客户端读取完成就对DFSInputStream调用close()方法释放。在读取数据时,如果
  DFSInputStream在与DataNode通信时遇到错误,会尝试从这个块的另外一个最邻近的DataNode读取数据。它也会记住那个故障的DataNode,以保证
  以后不会从那个故障DataNode节点反复读取后续的块数据。DFSInputStream也会通过校验和确认从DataNode发来的数据是否完整。如果发现有损坏的
  块,就在DFSInputStream试图从其他DataNode读取其副本之前通知NameNode。这个设计的一个重点是:NameNode告知客户端每个块中最佳的
  DataNode,并让客户端直接连接到该最佳DataNode上检索数据。由于数据流分散在集群中的所有DataNode上,所以这种设计能使HDFS可扩展到大量
  的并发客户端。同时,NameNode只需要响应块位置的请求(这些块位置信息存储在内存中,因而非常高效),无需响应数据请求,否则随着客户端数量
  的增长,NameNode会很快成为瓶颈。
    BufferedOutputStream out = new BufferedOutputStream(new FileOutputStream(new File(localPath)));
    IOUtils.copyBytes(in, out, 4096, true);

Hadoop的网络拓扑解释
    在本地网络中,两个节点被称为“彼此近邻”是指:在海里数据处理中,其主要限制因素是节点之间数据的传输速率-带宽很稀缺。这里的想法是将两个
  节点间的带宽作为军力的衡量标准。如果不用衡量节点间的带宽则很难实现(需要一个稳定的集群,并且在集群中两两节点对数量是节点数量的平方)。
  Hadoop为此采用了一种简单的方法:把网络当做一棵树,两个节点间的距离是它们到最近共同祖先的距离综合。该书中的层次是没有预先设定的,但是相对
  于数据中心、机架和正在运行的节点,通常可以设定等级。具体是针对以下每个场景,可用带宽一次递减,如下:
    同一节点上的进程
    同一机架上的不同节点
    同一数据中心的不同机架上的节点
    不同数据中心的节点
    
跨数据中心运行    
  目前到Hadoop-2.7仍然不适合跨数据中心运行。
    
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: