RDD分区2GB限制

本文目的

?

最近使用spark处理较大的数据时,遇到了分区2G限制的问题(ken)。找到了解决方法,并且在网上收集了一些资料,记录在这里,作为备忘。

?

问题现象

?

遇到这个问题时,spark日志会报如下的日志,

片段1


15/04/16 14:13:03 WARN scheduler.TaskSetManager: Lost task 19.0 in stage 6.0 (TID 120, 10.215.149.47): java.lang.IllegalArgumentException: Size exceeds Integer.MAX_VALUE
at sun.nio.ch.FileChannelImpl.map(FileChannelImpl.java:828)
at org.apache.spark.storage.DiskStore.getBytes(DiskStore.scala:123)
at org.apache.spark.storage.DiskStore.getBytes(DiskStore.scala:132)
at org.apache.spark.storage.BlockManager.doGetLocal(BlockManager.scala:517)
at org.apache.spark.storage.BlockManager.getLocal(BlockManager.scala:432)
at org.apache.spark.storage.BlockManager.get(BlockManager.scala:618)
at org.apache.spark.CacheManager.putInBlockManager(CacheManager.scala:146)
at org.apache.spark.CacheManager.getOrCompute(CacheManager.scala:70)

?

片段2


15/04/16 14:19:45 INFO scheduler.TaskSetManager: Starting task 20.2 in stage 6.0 (TID 146, 10.196.151.213, PROCESS_LOCAL, 1666 bytes)

15/04/16 14:19:45 INFO scheduler.TaskSetManager: Lost task 20.2 in stage 6.0 (TID 146) on executor 10.196.151.213: java.lang.IllegalArgumentException (Size exceeds Integer.MAX_VALUE) [duplicate 1]

15/04/16 14:19:45 INFO scheduler.TaskSetManager: Starting task 20.3 in stage 6.0 (TID 147, 10.196.151.213, PROCESS_LOCAL, 1666 bytes)

15/04/16 14:19:45 INFO scheduler.TaskSetManager: Lost task 20.3 in stage 6.0 (TID 147) on executor 10.196.151.213: java.lang.IllegalArgumentException (Size exceeds Integer.MAX_VALUE) [duplicate 2]

15/04/16 14:19:45 ERROR scheduler.TaskSetManager: Task 20 in stage 6.0 failed 4 times; aborting job

15/04/16 14:19:45 INFO cluster.YarnClusterScheduler: Cancelling stage 6

15/04/16 14:19:45 INFO cluster.YarnClusterScheduler: Stage 6 was cancelled

15/04/16 14:19:45 INFO scheduler.DAGScheduler: Job 6 failed: collectAsMap at DecisionTree.scala:653, took 239.760845 s

15/04/16 14:19:45 ERROR yarn.ApplicationMaster: User class threw exception: Job aborted due to stage failure: Task 20 in stage 6.0 failed 4 times, most recent failure: Lost task 20.3 in stage 6.0 (TID 147, 10.196.151.213): java.lang.IllegalArgumentException: Size exceeds Integer.MAX_VALUE

at sun.nio.ch.FileChannelImpl.map(FileChannelImpl.java:828)

?

注意红色高亮部分,异常就是某个partition的数据量超过了Integer.MAX_VALUE(2147483647 = 2GB)。

?

解决方法

?

手动设置RDD的分区数量。当前使用的Spark默认RDD分区是18个,后来手动设置为1000个,上面这个问题就迎刃而解了。可以在RDD加载后,使用RDD.repartition(numPart:Int)函数重新设置分区数量。

?

为什么2G限制

?

目前spark社区对这个限制有很多讨(tu)论(cao),spark官方团队已经注意到了这个问题,但是直到1.2版本,这个问题还是没有解决。因为牵涉到整个RDD的实现框架,所以改进成本相当大!

?

下面是一些相关的资料,有兴趣的读者可以进一步的阅读:

?

个人思(yu)考(jian)

?

这个限制有一定合理性。因为RDD中partition的操作是并发执行的,如果partition量过少,导致并发数过少,会限制计算效率。所以,基于这个限制,spark应用程序开发者会主动扩大partition数量,也就是加大并发量,最终提高计算性能。

?

以上只是一些个能思考,如果不正确,还请拍砖。

时间: 2024-07-29 15:19:49

RDD分区2GB限制的相关文章

【原创】大数据基础之Spark(7)spark读取文件split过程(即RDD分区数量)

spark 2.1.1 spark初始化rdd的时候,需要读取文件,通常是hdfs文件,在读文件的时候可以指定最小partition数量,这里只是建议的数量,实际可能比这个要大(比如文件特别多或者特别大时),也可能比这个要小(比如文件只有一个而且很小时),如果没有指定最小partition数量,初始化完成的rdd默认有多少个partition是怎样决定的呢? 以SparkContext.textfile为例来看下代码: org.apache.spark.SparkContext /** * Re

spark 中如何查看单个RDD分区的内容(创建分区,查看分区数)

spark 创建分区 val scores = Array(("Fred", 88), ("Fred", 95), ("Fred", 91), ("Wilma", 93), ("Wilma", 95), ("Wilma", 98)) val input = sc.parallelize(scores,3)   #这里创建了3个分区 查看分区数: input.partitions.size

Spark RDD 默认分区数量 - repartitions和coalesce异同

RDD.getNumPartitions()方法可以获得一个RDD分区数量, 1.默认由文件读取的话,本地文件会进行shuffle,hdfs文件默认会按照dfs分片来设定. 2.计算生成后,默认会按照executor-number*executor-cores来分片,也就是spark默认按照总工作核数来对数据分片,而不是工作实例数. RDD.repartitions(n:Int)和RDD.coalesce(n:Int,shuffle : Boolean) 都是对RDD进行重新分区. 源码实现上:

Spark弹性分布式数据集RDD

RDD(Resilient Distributed Dataset)是Spark的最基本抽象,是对分布式内存的抽象使用,实现了以操作本地集合的方式来操作分布式数据集的抽象实现.RDD是Spark最核心的东西,它表示已被分区,不可变的并能够被并行操作的数据集合,不同的数据集格式对应不同的RDD实现.RDD必须是可序列化的.RDD可以cache到内存中,每次对RDD数据集的操作之后的结果,都可以存放到内存中,下一个操作可以直接从内存中输入,省去了MapReduce大量的磁盘IO操作.这对于迭代运算比

RDD Join中宽依赖与窄依赖的判断

1.规律 如果JoinAPI之前被调用的RDD API是宽依赖(存在shuffle), 而且两个join的RDD的分区数量一致,join结果的rdd分区数量也一样,这个时候join api是窄依赖 除此之外的,rdd 的join api是宽依赖 2.测试程序 1 package com.ibeifeng.senior.join 2 3 import org.apache.spark.{SparkConf, SparkContext} 4 5 /** 6 * RDD数据Join相关API讲解 7

【Spark 深入学习-08】说说Spark分区原理及优化方法

本节内容 ------------------ · Spark为什么要分区 · Spark分区原则及方法 · Spark分区案例 · 参考资料 ------------------ 一.Spark为什么要分区    分区概念:分区是RDD内部并行计算的一个计算单元,RDD的数据集在逻辑上被划分为多个分片,每一个分片称为分区,分区的格式决定了并行计算的粒度,而每个分区的数值计算都是在一个任务中进行的,因此任务的个数,也是由RDD(准确来说是作业最后一个RDD)的分区数决定. 为什么要分区,这个借用

RDD之七:Spark容错机制

引入 一般来说,分布式数据集的容错性有两种方式:数据检查点和记录数据的更新. 面向大规模数据分析,数据检查点操作成本很高,需要通过数据中心的网络连接在机器之间复制庞大的数据集,而网络带宽往往比内存带宽低得多,同时还需要消耗更多的存储资源. 因此,Spark选择记录更新的方式.但是,如果更新粒度太细太多,那么记录更新成本也不低.因此,RDD只支持粗粒度转换,即只记录单个块上执行的单个操作,然后将创建RDD的一系列变换序列(每个RDD都包含了他是如何由其他RDD变换过来的以及如何重建某一块数据的信息

RDD之五:Key-Value型Transformation算子

Transformation处理的数据为Key-Value形式的算子大致可以分为:输入分区与输出分区一对一.聚集.连接操作. 输入分区与输出分区一对一 mapValues mapValues:针对(Key,Value)型数据中的Value进行Map操作,而不对Key进行处理. 方框代表RDD分区.a=>a+2代表只对( V1, 1)数据中的1进行加2操作,返回结果为3. 源码: [plain] view plain copy /** * Pass each value in the key-va

RDD之六:Action算子

本质上在Actions算子中通过SparkContext执行提交作业的runJob操作,触发了RDD DAG的执行. 根据Action算子的输出空间将Action算子进行分类:无输出. HDFS. Scala集合和数据类型. 无输出 foreach 对RDD中的每个元素都应用f函数操作,不返回RDD和Array,而是返回Uint. 图中,foreach算子通过用户自定义函数对每个数据项进行操作. 本例中自定义函数为println,控制台打印所有数据项. 源码: [plain] view plai