假设我有一个包含此类信息的大型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.0
到2012-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中运行,我将失去全局变量给出的控制,我不会考虑为我的情况解决方法
答案 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的数量设置为群集中的节点数,作为起点。应该运行得很好。
希望这有帮助。