Hadoop作业使用相同的reducer输出到同一个文件

时间:2012-10-23 11:51:13

标签: hadoop jobs output reducers

我遇到了一个有趣的情况,现在正在寻找如何故意这样做。在我的本地单节点设置中,我从终端屏幕同时运行了2个作业。我的两个作业都使用相同的reducer,它们只有map功能(聚合键 - group by)的差异,两个作业的输出都写入第一个作业的输出(虽然第二个作业确实创建了自己的文件夹,但它是空的)。我正在研究的是提供不同级别的汇总聚合,这种行为对我来说非常有吸引力,我可以在一个文件中使用两个不同级别的聚合输出(也完美排序)。

我的问题是如何在真正的Hadoop集群中实现相同的目标,我们有多个数据节点,即我以编程方式启动多个作业,所有访问相同的输入文件,以不同方式映射数据,但使用相同的reducer,输出是可在一个文件中使用,而不是在5个不同的输出文件中。

请告知。

在我决定提出问题之前,我正在查看merge output files after reduce phase

谢谢和亲切的问候,

莫伊兹艾哈迈德。

2 个答案:

答案 0 :(得分:0)

通常每个reducer任务在HDFS中生成一个单独的文件,因此reduce任务可以并行运行。如果要求是从reduce任务中获取一个o / p文件,则将作业配置为具有一个reducer任务。可以使用默认为1的mapred.reduce.tasks属性来配置Reducer的数量。这种方法的结果是只有一个reducer可能是完成作业的瓶颈。

另一种选择是使用一些其他输出格式,允许多个缩减器同时写入同一个接收器,如DBOuputFormat。作业处理完成后,可以将DB的结果导出到平面文件中。这种方法可以使多个reduce任务并行运行。

另一个选择是合并OP中提到的o / p文件。因此,根据每种方法的优缺点和要处理的数据量,可以选择其中一种方法。

答案 1 :(得分:0)

当不同的Mappers使用相同的输入文件,并使用相同的数据结构时,可以将所有这些不同映射器的源代码放入单个Mapper实现的单独方法中,并使用上下文中的参数来决定哪个映射要调用的函数。在这方面,您只需要启动一个Map Reduce Job。示例是伪代码:

class ComplexMapper extends Mapper {

protected BitSet mappingBitmap = new BitSet();

protected void setup(Context context) ... {
{
    String params = context.getConfiguration().get("params");
    ---analyze params and set bits into the mappingBitmap
}

protected void mapA(Object key, Object value, Context context){
.....
context.write(keyA, value);
}


protected void mapB(Object key, Object value, Context context){
.....
context.write(keyA, value);
}


protected void mapB(Object key, Object value, Context context){
.....
context.write(keyB, value);
}

public void map(Object key, Object value, Context context) ..... {
   if (mappingBitmap.get(1)) {
       mapA(key, value, context);
   }
   if (mappingBitmap.get(2)) {
       mapB(key, value, context);
   }
   if (mappingBitmap.get(3)) {
       mapC(key, value, context);
   }
}

原因是它可以通过界面等更优雅地实现。

在作业设置中添加:

Configuration conf = new Configuration();
conf.set("params", "AB");

Job job = new Job(conf);

正如Praveen Sripati所说,拥有一个输出文件将迫使您只使用一个可能对性能不利的Reducer。从hdfs下载时,您始终可以连接部分**文件。例如:

hadoop fs -text /output_dir/part* > wholefile.txt