为什么Spark RDD分区对HDFS有2GB的限制?

时间:2015-04-17 03:28:04

标签: scala apache-spark rdd

使用mllib RandomForest训练数据时出错。由于我的数据集很大,默认分区相对较小。所以抛出异常表示"大小超过Integer.MAX_VALUE" ,原始堆栈跟踪如下,

  

15/04/16 14:13:03 WARN scheduler.TaskSetManager:失去的任务19.0 in   阶段6.0(TID 120,10.215.149.47):   java.lang.IllegalArgumentException:大小超过Integer.MAX_VALUE
  在sun.nio.ch.FileChannelImpl.map(FileChannelImpl.java:828)at   org.apache.spark.storage.DiskStore.getBytes(DiskStore.scala:123)at at   org.apache.spark.storage.DiskStore.getBytes(DiskStore.scala:132)at at   org.apache.spark.storage.BlockManager.doGetLocal(BlockManager.scala:517)   在   org.apache.spark.storage.BlockManager.getLocal(BlockManager.scala:432)   在org.apache.spark.storage.BlockManager.get(BlockManager.scala:618)   在   org.apache.spark.CacheManager.putInBlockManager(CacheManager.scala:146)   在org.apache.spark.CacheManager.getOrCompute(CacheManager.scala:70)

Integer.MAX_SIZE是2GB,似乎有些分区内存不足。所以我将我的rdd分区重新分配到1000,这样每个分区可以保存比以前少得多的数据。最后,问题解决了!!!

所以,我的问题是: 为什么分区大小有2G限制?似乎没有为spark中的限制设置配置

3 个答案:

答案 0 :(得分:14)

spark中块的基本抽象是ByteBuffer,不幸的是它有一个Integer.MAX_VALUE(~2GB)的限制。

这是一个critical issue,可以防止在非常大的数据集中使用spark。 增加分区的数量可以解决它(如在OP的情况下),但并不总是可行的,例如当存在大的转换链时,其中一部分可以增加数据(flatMap等)或者数据是歪斜。

提出的解决方案是提出像LargeByteBuffer这样的抽象,它可以支持块的字节缓冲区列表。这会影响整体火花结构,因此它在相当长的一段时间内仍未得到解决。

答案 1 :(得分:0)

问题是,当使用Casandra,HBase或Accumulo之类的数据存储时,块大小基于数据存储拆分(可能超过10 gig)。从这些数据存储中加载数据时,您必须立即对1000个分区进行重新分区,以便可以操作数据而不会超出2gig的限制。

大多数使用spark的人并没有真正使用大数据;对他们来说,如果excel可以容纳更大的东西,或者对他们来说,Tableau是大数据;大多数是数据科学家,他们使用高质量的数据或使用足够小的样本量来处理极限值。

当处理大量数据时,我不得不返回mapreduce并仅在清理完数据后才使用spark。不幸的是,大多数火花社区对解决这个问题没有兴趣。

一个简单的解决方案是创建一个抽象并将字节数组用作默认值。但是,允许使用64位数据指针重载spark作业以处理大型作业。

答案 2 :(得分:0)

Spark 2.4.0 release通过将块数据复制为流来消除此限制。有关详细信息,请参见Spark-24926