用于大型数据集(10亿条记录)的Hadoop UniqValueCount映射和聚合缩减器

用于大型数据集(10亿条记录)的Hadoop UniqValueCount映射和聚合缩减器,hadoop,mapreduce,hadoop-streaming,elastic-map-reduce,Hadoop,Mapreduce,Hadoop Streaming,Elastic Map Reduce,我有一个数据集,大约有10亿个数据点。我想从中提取大约4600万个独特的数据点 我想使用Hadoop来提取唯一值,但在Hadoop上不断出现“内存不足”和Java堆大小错误-同时,我能够使用Python集(hashtable,如果您愿意的话)在单个框上相当轻松地运行此操作 我正在使用一个相当简单的算法来提取这些唯一值:我正在解析地图中的10亿行,并输出如下所示的行: UniqValueCount:I a UniqValueCount:I a UniqValueCount:I b

我有一个数据集,大约有10亿个数据点。我想从中提取大约4600万个独特的数据点

我想使用Hadoop来提取唯一值,但在Hadoop上不断出现“内存不足”和Java堆大小错误-同时,我能够使用Python集(hashtable,如果您愿意的话)在单个框上相当轻松地运行此操作

我正在使用一个相当简单的算法来提取这些唯一值:我正在解析地图中的10亿行,并输出如下所示的行:

UniqValueCount:I    a
UniqValueCount:I    a
UniqValueCount:I    b
UniqValueCount:I    c
UniqValueCount:I    c
UniqValueCount:I    d
然后运行“聚合”缩减器以获得结果,对于上述数据集,结果应如下所示:

I   4
这对于一小部分值来说效果很好,但是当我对10亿个数据点(如我所提到的,它们有4600万个键)运行它时,作业失败了

我在Amazon的Elastic Map Reduce上运行此功能,即使我使用六个m2.4XL节点(每个节点的最大内存为68.4 GB),作业也会失败,并出现“内存不足”错误

但是我能够使用Python代码在单个m1.large(一个小得多的具有8GB内存的框)上提取唯一值,该代码具有一组数据结构(哈希表)。我对Hadoop任务失败感到困惑,因为4600万个unique不应该占用那么多内存


出了什么问题?我使用UniqValueCount错误吗?

您可能在随机播放中遇到内存错误,请记住Hadoop在启动还原程序之前对键进行排序。大多数应用程序都不需要排序本身,但Hadoop使用它来聚合属于某个键的所有值

例如,您的映射器最终会多次写入相同的值,而您只关心给定键的unique数。以下是您现在正在做的事情:

Mapper output:
I -> a
I -> a
I -> a
I -> a
I -> b
I -> a
I -> b

Reducer input:
I -> [a, a, a, a, b, a, b]

Reducer output:
I -> 2
但你真的不需要写5*a或2*b在这种情况下,1次就足够了,因为你只关心unique。因此,与计算减速机中的唯一值不同,您可以通过确保每个值只发送一次来直接减少大量开销:

Mapper output:
I -> a
I -> b

Reducer input:
I -> [a, b]

Reducer output:
I -> 2
这将有效地减少网络带宽,并且洗牌将更加简单,因为将有更少的密钥进行排序

您可以通过两种方式完成此操作:

  • 在作业中添加一个组合器,该组合器将在映射器之后但在减速器之前运行,并且在发送到减速器之前只保留唯一性
  • 修改映射器以保留已发送内容的映射,如果以前已发送此映射,则不发送

这太棒了,非常感谢您的详细回复。我将尝试映射器(不确定如何在流模式下编写组合器),并让您知道它是如何工作的。您认为是在排序过程中遇到内存限制,还是减少了内存(这是我无法使用内存消息的减少器)?您可以使用
-combiner
选项指定组合器,但在版本0.21.0之前,这必须是一个Java类(已修复)。我认为您的内存问题仍然存在,如果我没有弄错的话,在jobtracker中可以看到的减量%中会报告洗牌步骤。