mapreduce—在hadoop中,是否可以将mapper的一部分发送到reducer,而将另一部分写入hdfs?

wvyml7n5  于 2021-06-03  发布在  Hadoop
关注(0)|答案(2)|浏览(285)

我想将Map器输出的一部分写入一个文件夹,比如hdfs中的文件夹a。输出的另一部分,我希望它由减速机处理。这可能吗?我知道有多种输出。是否可以使用多个输出?
谢谢!

lh80um4z

lh80um4z1#

您可以直接从Map器实现将输出写入hdfs—只需使用上下文的配置创建一个文件系统对象,然后创建一个文件,写入其中并记住关闭它:

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中唯一命名,因此可以用Map器id号作为文件名的后缀,但是您还需要考虑推测性执行(因为Map器任务示例可能在两个位置运行-两个位置都试图在hdfs中写入同一个文件)。
当输出提交者在tmp hdfs目录中创建带有任务id和尝试编号的文件时,通常会将其抽象出来,只会在提交该任务尝试时将其移动到正确的位置和文件名。在运行map-side(将数据写入本地文件系统)时,如果不关闭推测性执行或在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可以帮助您减少side,但我不认为map side可以工作,因为没有输出提交程序,工作目录也不在hdfs中。
当然,如果这只是一个Map器的工作,那么多次输出就可以了。因此,另一种方法是运行一个只Map的作业,然后在第二个作业中使用所需的输出部分(使用身份Map器)-这取决于您移动的数据量。

68bkxrlz

68bkxrlz2#

是的,可以使用multipleoutputs,根据docs,在map阶段通过multipleoutputs传递的任何输出都会被reducer忽略,所以这正是您想要的。我在github上写了一个小例子,希望你会发现它很有用。

相关问题