我有一个问题,我基本上想做这样的事情:
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
}
}
我知道最好避免这些情况,或者简单地在内存中实例化对象,但是我遇到了一个问题,我可能会有太多的东西要在内存中保存,并且将其分解成更多的reduce步骤会变得更加复杂。
似乎我不是一个人在寻找这个功能,事实上,它看起来像这是一段时间前实现的功能: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,给我一个类似的功能。我最接近的方法是使用streambackkediterator,它仍然在内存中积累对象,但似乎比ArrayList更节省内存。
有人知道在Hadoop 1.0.3中这样做的方法吗?
这是一个hack,但是您可以让您的Mapper发出每个值两次,但是在一次中设置一些标志,而在另一次中不设置。然后根据标记对值排序,然后根据你想要的自然顺序排序。然后,您必须执行一些自定义逻辑,以便在遇到第二组值时停止第一个循环。
除此之外,不,我没有看到一个简单的方法来做到这一点,而不是简单地将它们存储在内存中。主要问题是迭代器实际上并没有返回新对象,它返回的是相同的对象,但在调用next()
之间会发生变化。在幕后,Hadoop甚至可能不会缓存整个值集,所以重置迭代器将需要重新扫描文件(我猜他们在新版本中正在这样做)。