【问题标题】:HDFS distributed reads without Map/Reduce没有 Map/Reduce 的 HDFS 分布式读取
【发布时间】:2011-12-11 04:17:15
【问题描述】:

是否可以在一台机器上使用 HDFS 客户端从 HDSF 集群实现分布式读取?

我对一个由 3 个数据节点(DN1、DN2、DN3)组成的集群进行了实验。然后我从位于 DN1 的客户端程序的 10 个独立文件中同时读取 10 次,它似乎只从 DN1 读取数据。其他数据节点(DN2、DN3)显示零活动(从调试日志判断)。

我检查了所有文件的块是否在所有 3 个数据节点上复制,所以如果我关闭 DN1,那么数据将从 DN2 读取(仅限 DN2)。

增加读取的数据量没有帮助(尝试从 2GB 到 30GB)。

由于我需要读取多个大文件并仅从中提取少量数据(几 Kb),因此我想避免使用 map/reduce,因为它需要设置更多服务并且还需要写入输出每个拆分任务返回 HDFS。相反,将结果从数据节点直接流式传输回我的客户端程序会很好。

我正在使用SequenceFile 以这种方式(jdk7)读取/写入数据:

//Run in thread pool on multiple files simultaneously

List<String> result = new ArrayList<>();
LongWritable key = new LongWritable();
Text value = new Text();
try(SequenceFile.Reader reader = new SequenceFile.Reader(conf,
                                     SequenceFile.Reader.file(filePath)){
  reader.next(key);
  if(key.get() == ID_I_AM_LOOKING_FOR){
    reader.getCurrentValue(value);
    result.add(value.toString());
  }
}

return result; //results from multiple workers are merged later

任何帮助表示赞赏。谢谢!

【问题讨论】:

    标签: hadoop hdfs


    【解决方案1】:

    恐怕您看到的行为是设计使然。来自Hadoop document

    副本选择

    为了最小化全局带宽消耗和读取延迟,HDFS 尝试 满足来自最接近的副本的读取请求 读者。如果与阅读器节点在同一机架上存在副本, 然后首选该副本来满足读取请求。如果昂格/ HDFS 集群跨越多个数据中心,然后是一个副本 驻留在本地数据中心优于任何远程 复制品。

    可以通过对应的Hadoop source code进一步确认:

      LocatedBlocks getBlockLocations(...) {
        LocatedBlocks blocks = getBlockLocations(src, offset, length, true, true);
        if (blocks != null) {
          //sort the blocks
          DatanodeDescriptor client = host2DataNodeMap.getDatanodeByHost(
              clientMachine);
          for (LocatedBlock b : blocks.getLocatedBlocks()) {
            clusterMap.pseudoSortByDistance(client, b.getLocations());
    
            // Move decommissioned datanodes to the bottom
            Arrays.sort(b.getLocations(), DFSUtil.DECOM_COMPARATOR);
          }
        }
        return blocks;
      }
    

    也就是说,如果前一个失败了,所有可用的副本都会一个接一个地尝试,但最近的总是第一个。

    另一方面,如果您通过HDFS Proxy 访问HDFS 文件,它会选择数据节点randomly。但我认为这不是你想要的。

    【讨论】:

    【解决方案2】:

    除了 Edwardw 所说的,请注意您当前的集群非常小(只有 3 个节点),在这种情况下,您会看到所有节点上的文件。发生这种情况是因为 Hadoop 的默认复制因子也是 3。在更大的集群中,您的文件不会在每个节点上都可用,因此访问多个文件可能会转到不同的节点并分散负载。

    如果您使用较小的数据集,您可能需要查看 HBase,它可以让您使用较小的块并在节点之间分散负载(通过分割区域)

    【讨论】:

    • 你是对的。我实际上已经尝试将复制设置为 1 以尝试在集群中均匀分布块,但它最终将它们全部写入 DN1 :(( 我想我需要更多数据和块才能开始在不同节点之间平衡它们。感谢您的 HBase 提示,我可以从那里借鉴一些想法。
    【解决方案3】:

    我会说你的案子对 MR 来说听起来不错。如果我们抛开特定的 MR 计算范式,我们可以看出 hadoop 的构建是为了将代码带到数据中,而不是相反。将代码移至数据对于获得可扩展的数据处理至关重要。
    另一方面 - 设置 MapReduce 比 HDFS 更容易 - 因为它在作业之间不存储任何状态。
    同时 - MR 框架会为您关心并行处理 - 这需要时间才能正确完成。
    另一点 - 如果数据处理的结果如此之小 - 如果您将它们组合在 reducer 中,则不会对性能产生重大影响。
    换句话说 - 我建议重新考虑使用 MapReduce。

    【讨论】:

    • 如果你能给我一些信息,我会试着用估计来回答。
    • 谢谢。这非常简单,基本上是对日志数据的大文件进行类似 grep 的搜索。日志数据可以是任意内容。我有两种类型的搜索:1)对内容进行类似 grep 的子字符串/正则表达式匹配 2)寻找已知的日志位置(位置/id 单独存储)并获取内容。您可以假设结果集总是很小:0~100 个日志。我也在使用块压缩(使用SequenceFile API)。
    • 对于日志数据,以输入格式的形式有一些非正规化层可能会很方便。如果您想减少解析/对象创建开销 - 您可以在 RecordReader 中从 HDFS 流中读取数据时进行一些过滤。您的性能要求/期望是什么?
    猜你喜欢
    • 2014-08-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-03-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多