如何在hadoop 1.0.3中无需缓存的情况下多次迭代hadoop可迭代的值?

时间:2013-03-06 23:43:18

标签: java hadoop iterator mapreduce amazon-emr

我有一个问题,我基本上想做这样的事情:

    public void reduce(Text key, Iterable<Text> iterValues, Context context){

           for (Text val : iterValues){
               //do something
           }

           iterValues.reset()
           for (Text val : iterValues){
               //do something else
           }
}

我知道最好避免这些情况,或者只是简单地在内存中实例化对象,但是我遇到了一个问题,即我可能会有太多的事情需要保留在内存中,并且在结构上要复杂得多这需要更多的减少步骤。

看起来我并不是唯一一个寻找这个功能的人,事实上它看起来像是刚才实现的功能: https://issues.apache.org/jira/browse/HADOOP-5266

MarkableIterator类似乎正是我正在寻找的:http://hadoop.apache.org/docs/current/api/org/apache/hadoop/mapreduce/MarkableIterator.html

然而,它似乎只在hadoop 2.0.3-alpha中可用。我想在EMR中运行它,它只支持1.0.3(我目前正在使用的)或0.20.205。我一直在尝试各种各样的东西,但我没有在1.0.3中找到任何能给我类似功能的东西。我最接近的是使用StreamBackedIterator,它仍然在内存中累积对象,但似乎比ArrayList更有效。

是否有人知道在Hadoop 1.0.3中执行此操作的方法?

1 个答案:

答案 0 :(得分:1)

这有点像黑客,但是你可以让你的Mapper每次发出两次值,但是有一个标志设置在一个而不是另一个。然后首先根据该标志对值进行排序,然后根据您想要的任何自然顺序排序。然后,当你点击第二组值时,你将不得不做一些自定义逻辑来停止第一个循环。

除此之外,不,我没有看到一个简单的方法来做到这一点,而不是简单地将它们存储在内存中。主要问题是迭代器实际上并没有返回新对象,它返回相同的对象,但在调用next()之间发生变化。在幕后,Hadoop甚至可能不会缓存整个值集,因此重置迭代器将需要重新扫描文件(我猜他们在新版本中正在进行)。