Hadoop:将文件或文件路径发送到地图会减少作业

时间:2013-07-02 05:24:23

标签: file hadoop path mapreduce streaming

假设我有使用hadoop map-reduce处理的N个文件,我们假设它们很大,远远超出块大小,并且只有几百个。现在我想处理这些文件中的每一个,让我们假设单词计数示例。

我的问题是:创建一个map-reduce作业,其输入是一个文本文件和每个文件的路径,而不是将每个文件直接发送到map函数,即连接所有文件并将推送到不同的地图制作者[编辑]

这些都是有效的方法吗? 它们有任何缺点吗?

感谢您的快速回答,我已经详细描述了我的问题,因为我的抽象可能遗漏了一些重要主题:

我的应用程序中有Hadoop HDFS上的N个小文件,我只需要处理每个文件。所以我使用map函数将python脚本应用于每个文件(实际上是图像[我已经查看了所有hadoop图像处理链接]),我知道小文件问题,典型的建议是将较小的文件分组,以避免移动文件的开销(使用序列文件的基本建议或创建自己的数据结构,如HIPI的情况)。

这让我觉得我们不能告诉每个映射器查找本地文件并对其进行操作吗?

我还没有找到解决该问题的方法,这就是为什么我要查找向每个映射器发送文件的路径或者自己发送文件的原因。

为每个图像集创建一个路径名列表似乎没问题,但正如评论中所提到的,我放松了数据局部性属性。

现在,当我查看hadoop流接口时,它提到不同的部分基于stdin和stdout进行通信,这些stdout通常用于文本文件。这就是我感到困惑的地方,如果我只是发送一个路径名列表,这应该不是问题,因为每个映射器只会尝试找到它所分配的图像集合。但是,当我查看单词计数示例时,输入是文件,然后在整个映射器和之间进行拆分,这样当我感到困惑时,我是否应该将图像连接成组然后发送这些连接组就像文本文档到不同的映射器或者如果我应该连接图像将它们留在hadoop HDFS然后只是将路径传递给映射器 ...我希望这是有意义的...也许我完全在这里...

再次感谢!

3 个答案:

答案 0 :(得分:2)

两者都有效。但是后者会产生额外的开销,性能会下降,因为你正在谈论将所有文件连接成一个文件并将其提供给1个映射器。通过这样做,你将违背Hadoop的最基本原则之一,parallelism。并行性使Hadoop如此高效。

仅供参考,如果您确实需要这样做,则必须在isSplittable类中将InputFormat设置为false,否则框架将拆分文件(基于您的InputFormat)。

就输入路径而言,您只需要给出输入目录的路径。该目录中的每个文件都将在没有人为干预的情况下进行处理。

HTH


回复您的修改:

我想你有点误解了这一点。您不必担心本地化。 Hadoop负责这一点。您只需运行您的工作,数据将在其存在的节点上处理。文件的大小与它无关。你不必告诉地图制作者。过程如下:

您将工作提交给JT。 JT指示TT在节点上运行,该节点具有作业所需的数据块以开始启动映射器。如果插槽被某些其他进程占用,则在具有数据块的某个其他节点上发生同样的事情。

答案 1 :(得分:0)

如果您正在如上所述在单个映射器中处理整个连接文件,那么瓶颈将存在。

如果您将连接文件作为Hadoop的输入提供,那将不会有问题。因为,形成的大文件显然会在HDFS中分发(我假设您使用的是HDFS),并且将同时由多个Mappers和Reducer处理。

答案 2 :(得分:0)

  

我的问题是:创建一个map-reduce作业,其输入是一个文本文件和每个文件的路径,而不是将每个文件直接发送到map函数,即连接所有文件并将它们推入一个映射器。

通过在文本文件中列出文件路径并(我假设)在映射器中手动打开它们,您将击败数据局部性(这是hadoop将尝试运行映射器代码的地方,而不是数据将数据移动到代码执行的位置。使用1000个文件,这也可能由单个映射器实例处理(我想1000行文本应该小于块大小)。

如果先连接所有文件然后再用作输入,这通常效率较低,主要是因为你将所有文件复制到一个节点(连接它们)然后将数据推回到HDFS作为单个文件。这甚至在您再次在映射器中处理文件之前(或者更多取决于输入格式分割/压缩编解码器的可分割性)。

如果您要多次处理此连锁文件,并且每个文件小于块大小,则将它们合并到单个文件可能会有所帮助,但您已经注意到每个文件都大于默认值块大小。

您是否有特殊原因希望所有文件都通过单个映射器(这听起来就像您尝试通过这两个选项实现的那样)。