在重新分区时Spark OutOfMemory

时间:2017-12-22 14:39:37

标签: apache-spark

我在Spark中遇到OutOfMemory异常,这在进行重新分区时会被抛出。该程序正在处理以下步骤:

JavaRDD<A> data = sc.objectFile(this.inSource);
JavaPairRDD<String, A> dataWithKey = data.mapToPair(d -> new Tuple2<>(d.getUjid(), d));
JavaPairRDD<ADesc, AStats> dataInformation = dataWithKey.groupByKey()
            .flatMapToPair(v -> getDataInformation(v._2()));
dataInformation.groupByKey().repartition(PARTITIONS).map(v -> merge(v._1(), v._2()));

getDataInformation将一组具有相同id的数据点映射到几个新的数据点:

Iterable<Tuple2<ADesc, AStats>> getDataInformation(Iterable<A> aIterator)

例如为: (ID1,Data1),(ID1,Data2),(ID1,Data3) - &gt; (Data_Description_1,Stats1),(Data_Description_2,Stats2)

信息:

  • A是包含一些信息的数据结构。这是一个非常基本的结构。
  • 每个数据点A作为ID和几个数据点共享一个公共ID。因此,我们将每个数据点映射到元组(ID,A)
  • 我们按ID对数据点进行分组,并使用getDataInformation提取几个新的数据点。
  • 之后我们想要对相同数据描述的所有统计信息进行分组并合并它们。

合并时我们得到一个OutOfMemory。因此,我们插入一个重新分区并耗尽内存。包括flatMapToPair在内的所有阶段都能正常工作。我们为PARTITIONS尝试了不同的值,直到我们完成了5000个任务,大多数任务都没有多少工作要做,而有些任务必须进行几MB,3个任务(独立于分区数)总是耗尽内存。我的问题是为什么火花会使数据非常不平衡并且在进行重新分配时内存不足?

Bug

1 个答案:

答案 0 :(得分:0)

我解决了我的问题,并简要介绍了一下。也许有人会在将来发现它有用。

问题在于     dataInformation.groupByKey()。repartition(PARTITIONS).map(v - &gt; merge(v._1(),v._2()));

我有很多具有应该合并的密钥的对象,因此很多对象都在同一个分区上,任务就是OOM。我更改了代码并使用了reducedByKey并修改了合并函数,它不会将所有对象与相同的键合并,而是使用相同的键合并2个对象。因为函数是关联的,结果是相同的。

简而言之:groupByKey将许多对象分组为一个任务