2012-05-25 36 views
1

如何将Mapper中收集的少量元数据传递给Reducer?在我的具体问题中,我只想通过两个长的值,所以我不会使用MultipleOutputFormatMultipleOutputs这些。

一些变体我曾尝试:将少量值从Mapper传递到Reducer

(1)

映射

context.getCounter("Countergroup", "Counter").increment(1); 

减速

counter = context.getCounter("Countergroup", "Counter").getValue(); 

计数器不定时更新,所以Reducer中的函数调用将返回0值。



(2)

映射

context.getConfiguration().setInt("Counter", countTotal); 

减速

counter = context.getConfiguration().getInt("Counter", 0);   

当然配置不能运行作业期间改变(是值得一试)。

已经有关于这个问题的问题,但我找不到工作答案。此外,API已经改变。我正在使用Hadoop 0.20.2。



类似的问题:

Passing values from Mapper to Reducer

Accessing a mapper's counter from a reducer (这看起来很有希望,但它好像它不与0.20.2 API工作)

+0

尝试动物园管理员。 –

+0

这里不可能。 – DMolloy

回答

0

如果你不能找到解决方案(使用计数器将您的问题的解决方案(从映射器传递给Reducer中的两个较长的值),另一种方法可以利用订单倒置的模式。

在这种模式中,你所做的是从map中发出一个额外的键值对,其中键是东西,它成为第一个键缩减器接收的事件(利用reducer以排序顺序接收键的事实)。例如,如果您发出的键是从1到1000的数字值。您的虚拟键可以是“0”。由于Reducer以排序顺序接收密钥,所以在任何其他密钥之前处理虚拟密钥是有保证的。

You additionaly在新API中有SetUp()和CloseUp()方法(旧API中也有类似的方法,但我不记得名字),以利用它们只执行一次的事实在每个节点上,在该节点上的所有map/reduce任务之前/之后开始/结束。

+0

只有当你只有一个减速器时才有效。我从OP的问题中得到的理解是,这个元数据需要被所有的缩减者使用,而不仅仅是那些碰巧运行并获得特殊密钥的元数据。如果您可以减少数据膨胀,则可以将元数据复用到所有密钥,从而确保每次调用reduce()时都能看到它,并且您可以执行一些额外的辅助排序技巧来确保在迭代时首先查看元数据值群组。 –

+0

是的,我同意它只适用于1减速器,除非数据足够大,程序使用1减速器时速度太慢。否则,您可以发出多个键并写入自定义分区器。我同意发出多个密钥可能不是很干净,但是它是一种权衡,每个键值对都发出元数据并进行二次排序,因为后一种方法会让您使用大量不必要的内存。 –

+0

现在* *我喜欢(自定义分区)。通过分区器发出尽可能多的密钥,并通过分区器确保每个reducer获取一个副本,并通过自定义比较器确保元数据密钥在所有真实密钥之前出现。 –