是什么决定了减速器的数量以及如何避免减速器的瓶颈?

时间:2013-10-16 19:06:07

标签: java hadoop mapreduce

假设我有一个包含此类信息的大型tsv文件:

2012-09-22 00:00:01.0   249342258346881024  47268866    0   0   0   bo
2012-09-22 00:00:02.0   249342260934746115  1344951     0   0   4   ot
2012-09-22 00:00:02.0   249342261098336257  346095334   1   0   0   ot
2012-09-22 00:05:02.0   249342261500977152  254785340   0   1   0   ot

我想实现一个MapReduce作业,该作业枚举五分钟的时间间隔并过滤tsv输入的一些信息。输出文件如下所示:

0 47268866  bo
0 134495    ot
0 346095334 ot
1 254785340 ot

密钥是间隔的编号,例如,0是2012-09-22 00:00:00.02012-09-22 00:04:59之间的间隔的参考。

我不知道这个问题是否适合MapReduce方法或者我认为不对。在map函数中,我只是将时间戳作为键传递,将过滤后的信息作为值传递。在reduce函数中,我使用全局变量计算间隔并生成所提到的输出。

i。框架是否自动确定某些减速器的数量,或者是用户定义的?有了一个reducer,我认为我的方法没有问题,但是我想知道在处理非常大的文件时,一个reduce是否会成为瓶颈,是吗?

ii。如何使用多个Reducer解决此问题?

任何建议都会非常感激! 提前谢谢!

修改

@Olaf回答了第一个问题,但第二个问题仍然让我对并行性有所怀疑。我的map函数的地图输出目前是这个(我只是以精确的精度传递时间戳):

2012-09-22 00:00   47268866    bo
2012-09-22 00:00   344951      ot
2012-09-22 00:00   346095334   ot
2012-09-22 00:05   254785340   ot

因此在reduce函数中,我收到输入,键表示收集信息时的分钟数和信息本身的值,我想枚举从0开始的五分钟间隔。我当前正在使用全局变量来存储间隔的开始,当一个键推断它时,我正在递增间隔计数器(这也是一个全局变量)。

以下是代码:

private long stepRange = TimeUnit.MINUTES.toMillis(5);
private long stepInitialMillis = 0;
private int stepCounter = 0;

@Override
public void reduce(Text key, Iterable<Text> values, Context context)
        throws IOException, InterruptedException {

    long millis = Long.valueOf(key.toString());
    if (stepInitialMillis == 0) {
        stepInitialMillis = millis;
    } else {
        if (millis - stepInitialMillis > stepRange) {
            stepCounter = stepCounter + 1;
            stepInitialMillis = millis;
        }
    }
    for (Text value : values) {
        context.write(new Text(String.valueOf(stepCounter)),
                new Text(key.toString() + "\t" + value));
    }
}

所以,使用多个reducers,我将在两个或多个节点上运行reduce函数,在两个或更多JVM中运行,我将失去全局变量给出的控制,我不会考虑为我的情况解决方法

2 个答案:

答案 0 :(得分:2)

减少器的数量取决于群集的配置,但您可以限制MapReduce作业使用的减速器数量。

如果您处理大量数据,单个reducer确实会成为MapReduce作业的瓶颈。

Hadoop MapReduce引擎保证将与相同密钥关联的所有值发送到同一个reducer,因此您的方法应该适用于multile reducer。见雅虎!详细教程:http://developer.yahoo.com/hadoop/tutorial/module4.html#listreducing

编辑:为了保证同一时间间隔内的所有值都转到同一个reducer,您必须使用时间间隔的某个唯一标识符作为键。您必须在映射器中执行此操作。我正在再次阅读你的问题,除非你想以某种方式汇总对应于相同时间间隔的记录之间的数据,否则根本不需要任何减速器。

编辑:正如@SeanOwen指出的那样,reducers的数量取决于集群的配置。通常,它配置为每个节点的最大任务数乘以数据节点数的0.95和1.75倍。如果未在群集配置中设置mapred.reduce.tasks值,则默认的reducers数为1。

答案 1 :(得分:1)

看起来你想要将一些数据聚合五分钟。使用Hadoop进行Map-reduce非常适用于此类事情!应该没有理由使用任何“全局变量”。我将如何设置它:

映射器读取TSV的一行。它抓取时间戳,并计算它所属的五分钟桶。将其作为字符串,并将其作为键发出,如“20120922:0000”,“20120922:0005”,“20120922:0010”等至于与该键一起发出的值,只需保持简单开头,并将整个制表符分隔的行作为另一个Text对象发送。

既然mapper已经确定了数据的组织方式,那么减速器的工作就是进行聚合。每个reducer将获得一个密钥(五分钟buckers中的一个),以及适合该桶的所有行的列表。它可以迭代该列表,并从中提取它想要的任何内容,根据需要将输出写入上下文。

对于地图制作者,让hadoop想出那个部分。将reducers的数量设置为群集中的节点数,作为起点。应该运行得很好。

希望这有帮助。