如何在单个 MapReduce 作业中实现多个 reducer

How to implement multiple reducers in a single MapReduce Job

我有一个庞大的数据集,我需要对相同的数据执行不同的功能。 我想要四个输出文件。由于四个操作不同,我可以使用四个 partitioners 和四个 reducers 来实现吗?是否有可能或者我是否需要编写四个作业来执行此操作?请帮助我!

您只需要在 MapReduce 中指定 reducer 的数量 工作配置。默认的partitioner会根据指定reducer的key模数的hash将数据分发给reducers。

要覆盖默认分区程序的行为,您可以实现自己的自定义分区程序,指定您的数据应如何传输到缩减器。

---编辑在评论区回答问题---

如何在 Map-reduce 驱动中指定多个 reducer class

要设置reducer的数量,在job conf中你可以像下面这样设置-

int numReducers = /*number of reducers you want*/;
job.setNumReduceTasks(numReducers);

要不要为此写四个不同的Job。或者我可以用一个 Job

Hadoop MR 作业 I/O 密集,在您的 MR 作业设计中,您应该尽可能减少 I/O 和并行处理。

如果您的减速器需要相同的输入来生成所有 4 个输出,最好保持单一作业,但另一个考虑因素可能是任一输出的数据偏斜。 例如 output1 有更多的处理时间 + 大部分传入数据可能会为 output1 处理。 如果你有这样的场景,比如处理 output1 所花费的时间比处理 output2 + output3 + output4 所花费的总时间要长得多,那么你应该考虑将 output1 的处理分成多个步骤。

但是,如果我们考虑所有 4 个输出具有或多或少相等的处理时间并且自始至终消耗相同的数据, 最好在 reducer 中有一些条件处理逻辑,让您的自定义 partioner 决定哪些数据进入哪个 reducer。

您的自定义 partioner 可以进行一些检查,例如传入的数据是否有资格为 "GC content" 做出贡献,因此让它进入 Reducer 3。 但是,如果您的传入数据需要处理多于一个 output/distribution,请使用条件处理并从同一个 reducer 写入多个输出文件,请使用 "MultipleOutputs"。 您可以 google 查找使用示例,它允许您从 Mapper 或 Reducer 中同时将输出写入多个 folders/files。

Hadoop 允许您从作业驱动程序中指定 reducer 任务的数量 job.setNumReduceTasks(num_reducers);。由于您需要四个输出,因此您可以指定 int num_reducers = 4; 这是一个示例驱动程序 class。

public class run {

    public static void main(String[] args) throws Exception {

        Configuration conf = new Configuration();
        Job job = new Job(conf, "Run NB Count");

        job.setJarByClass(NB_train_hadoop.class);
        // set mappers, reducers, other stuff
        job.setNumReduceTasks(num_reducers);

        FileInputFormat.addInputPath(job, new Path(args[0]));
        FileOutputFormat.setOutputPath(job, new Path(args[1]));
        System.exit(job.waitForCompletion(true) ? 0 : 1);
    }
}

虽然这很方便,但您必须明白,您可以选择最佳的 reducer 数量,具体取决于集群中的节点数量。

例如,运行 4个亚马逊m3.xlarge实例(1主,3从,4核一个实例),wall time和reducer task数量之间有如下关系MapReduce 作业。您可以看到,更多不一定更好,如果您使用太多,那么您不妨用您母亲的卷发器处理您的数据,因为这样会更快。

希望对您有所帮助!!

第一种方法

我认为你应该在一个独特的 reduce 方法中实现代码,并根据执行的过程发出 n 个键。例如:您实施 A、B、C 和 D 技术,然后,在您的映射器中您可以实施此(伪代码):

dataA = ProcessA(key,value)
context.write("A", dataA)
dataB = ProcessB(key,value)
context.write("B", dataB)
dataC = ProcessC(key,value)
context.write("C", dataC)
dataD = ProcessD(key,value)
context.write("D", dataD)

您应该注意输出的数据类型。此外,输出密钥可能更复杂。

第二种方法

您可以在同一个 java 项目中生成 N 个 MapReduce 应用程序,然后重新使用该 Map,并开发 N 个 reducer。

job.setReducerClass 中,在每个主要 class 中设置每个 Reducer。地图将是相同的。