目标:实施Reduce Side Join
我的代码中目前有Job Chaining(两个工作)。现在我想在另一份工作中实现在reduce方面的加入。我必须采取多种投入:
Input #1:
上一个减速机的输出
Input #2:
来自HDFS的新文件实现加入。
看了一些关于如何使用MultipleInputs.addInputhPath(job, Path, InputFormat.class, Mapper.class);
所以我知道我必须使用它两次,一次用于Input #1
,一次用于Input #2
。
Question 1:
然后,如果我使用两个单独的映射器和一个reducer,将首先执行哪个映射器(或者它们将并行执行)?如何检查reducer端哪个映射器发出了<key, value>
对?
Question 2:
如果我使用单个映射器和单个reducer,那么控制流程是什么?
Question 3:
更多的黑客,即不使用MultipleInputs
使用DistributedCache
在reducer的Input #2
方法中加载setup()
是否可行(性能明智)?并将前一个reducer的输出作为该作业的唯一输入。
Note:
Input #2
文件的大小非常小。
答案 0 :(得分:1)
回答1:
两个Mappers的Map
任务应该运行并行提供的插槽可用。单个插槽的存在可能导致它们按顺序运行(可能有交错),但这不是正常情况。如果Mapper序列有一些配置,我就不知道这一点。
我再次怀疑任何api
可用于识别哪个Mapper发出<key, value>
。确切地说,只需要识别value
,因为不同的地图可能会发出相同的key
。这通常通过在输出值中添加前缀标记并在reducer中解析这些标记来实现。例如:
if(value.toString.startsWith("Input#1")){ //processing code }
看看这个blogpost,它有所有必需的提示和技巧。请注意,所有这些示例都使用旧的mapred
api。但无论如何,逻辑都是一样的。
回答2:
如果没有MultipleInputs
,则Map
中必须使用可用的Context
对象标识传入对的文件名。例如:
public void map(LongWritable key, Text value, Context context)
throws IOException, InterruptedException {
String fileName = ((FileSplit) context.getInputSplit()).getPath().getName();
//............
}
然后只需将一个合适的标签添加到输出值,其余与answer1相同。
回答3:
这很棘手。当要添加到缓存的文件很小时,使用DistributedCache
来加强提升性能。这可能是因为该作业现在以较少的Map
任务运行。但它会对大文件产生不利影响。困境是要知道DistributedCache
有多少字节被认为是小的。
由于您提到Input#2文件非常小,这应该是您最合适的解决方案。
注意:这篇文章的很多评论都是基于意见的。期待专家的投入。