是否可以在hadoop中将映射器的一部分发送到reducer,同时将另一部分写入HDFS



我想把映射器输出的部分写入一个文件夹,比如HDFS中的文件夹a。输出的另一部分,我希望它由减速器处理。这可能吗?我知道多重输出。这是否可以使用多个输出?

谢谢!

是的,可以使用MultipleOutput,根据文档,在映射阶段通过MultipleOutput传递的任何输出都会被reducer忽略,所以这正是您想要的。我在我的GitHub上写了一个小例子,希望你会觉得它有用。

您可以从映射器实现直接将输出写入HDFS-只需使用上下文的配置创建一个FileSystem对象,然后创建一个文件,写入并记住关闭它:

public void cleanup(Context context) {
FileSystem fs = FileSystem.get(context.getConfiguration());
PrintStream ps = new PrintStream(fs.create(
new Path("/path/to/output", "map-output")));
ps.println("test");
ps.close();
}

其他需要考虑的事项-每个文件都需要在HDFS中唯一命名,这样您就可以在文件名后面加上映射器ID号,但您也需要了解推测性执行(因为您的映射器任务实例可能在两个位置运行,都试图在HDFS中将同一个文件写入)。

当Output Committer在tmp HDFS目录中创建具有任务ID和尝试编号的文件时,通常会将其抽象出来,只会在提交该任务尝试时将其移动到正确的位置和文件名。在运行映射端(数据写入本地文件系统)时,如果不关闭推测执行或在HDFS中创建多个文件(每次尝试一个),就无法解决这个问题。

因此,一个更"完整"的解决方案看起来像:

FileSystem fs = FileSystem.get(context.getConfiguration());
PrintStream ps = new PrintStream(fs.create(new Path(
"/path/to/output", String.format("map-output-%05d-%d",
context.getTaskAttemptID().getTaskID().getId(),
context.getTaskAttemptID().getId()))));
ps.println("test");
ps.close();

MultipleOutputs将帮助您减少侧边,但我认为映射侧边不会起作用,因为没有输出提交器,工作目录也不在HDFS中。

当然,如果这只是一个映射器的工作,那么MultipleOutput就会起作用。因此,另一种方法是运行一个仅映射的作业,然后在第二个作业中使用所需的输出部分(使用身份映射器)——我想这取决于你移动了多少数据。

最新更新