用于大型数据集(10亿条记录)的hadoop uniqvaluecountMap和聚合缩减器

3mpgtkmj  于 2021-06-04  发布在  Hadoop
关注(0)|答案(1)|浏览(342)

我有一个数据集,大约有10亿个数据点。我想从中提取4600万个独特的数据点。
我想使用hadoop来提取唯一的值,但是在hadoop上不断出现“内存不足”和java堆大小错误——同时,我能够使用python集(hashtable,如果您愿意的话)在单个框上相当容易地运行这个程序
我正在使用一个相当简单的算法来提取这些唯一的值:我正在解析Map中的10亿行,并输出如下所示的行:

UniqValueCount:I    a
UniqValueCount:I    a
UniqValueCount:I    b
UniqValueCount:I    c
UniqValueCount:I    c
UniqValueCount:I    d

然后运行“aggregate”reducer来得到结果,对于上面的数据集应该是这样的:

I   4

这对于一小部分值很有效,但是当我对10亿个数据点(如我所提到的,有4600万个键)运行它时,作业失败了。
我在amazon的elastic map reduce上运行它,即使我使用6个m2.4XL节点(每个节点的最大内存为68.4 gb),作业也会失败,并出现“内存不足”错误。
但是我能够使用python代码在一个m1.large(一个小得多的带有8gb内存的框)上提取唯一的值,该代码具有一组数据结构(哈希表)。我很困惑hadoop作业失败了,因为4600万个unique不应该占用那么多内存。
会出什么问题?我使用uniqvaluecount时出错了吗?

7vux5j2d

7vux5j2d1#

您可能在无序排列中遇到内存错误,请记住hadoop在启动还原程序之前对键进行排序。排序本身对于大多数应用程序来说不是必需的,但是hadoop使用它来聚合属于一个键的所有值。
对于您的示例,Map器最终会编写很多次相同的值,而您只关心给定键的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

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

Mapper output:
I -> a
I -> b

Reducer input:
I -> [a, b]

Reducer output:
I -> 2

这将有效地减少网络带宽,并且洗牌将更简单,因为将有更少的密钥进行排序。
你可以通过两种方式来实现:
在作业中添加一个组合器,该组合器将在Map器之后但在reducer之前运行,并且在发送到reducer之前只保留uniques。
修改Map器以保留已发送内容的Map,如果以前已发送此Map,则不发送。

相关问题