Apache spark 如果RDD变大,Spark将如何反应?

Apache spark 如果RDD变大,Spark将如何反应?,apache-spark,Apache Spark,我们有在ApacheSpark中运行的代码。在详细检查代码之后,我确定我们的一个映射程序正在修改RDD中的对象,而不是为输出制作对象的副本。也就是说,我们有一个dict的RDD,map函数向字典中添加内容,而不是返回新的字典 RDD应该是不可变的。我们的基因正在变异 我们也有内存错误 问题:如果RDD的大小突然增加,Spark会感到困惑吗?虽然它可能不会崩溃,但它可能会导致一些未指定的行为。例如,这个片段 val rdd = sc.parallelize({ val m = new mu

我们有在ApacheSpark中运行的代码。在详细检查代码之后,我确定我们的一个映射程序正在修改RDD中的对象,而不是为输出制作对象的副本。也就是说,我们有一个dict的RDD,map函数向字典中添加内容,而不是返回新的字典

RDD应该是不可变的。我们的基因正在变异

我们也有内存错误


问题:如果RDD的大小突然增加,Spark会感到困惑吗?

虽然它可能不会崩溃,但它可能会导致一些未指定的行为。例如,这个片段

val rdd = sc.parallelize({
    val m = new mutable.HashMap[Int, Int]
    m.put(1, 2)
    m
} :: Nil)
rdd.cache() // comment out to change behaviour!
rdd.map(m => {
    m.put(2, 3)
    m
}).collect().foreach(println) // "Map(2 -> 3, 1 -> 2)"
rdd.collect().foreach(println) // Either "Map(1 -> 2)" or "Map(2 -> 3, 1 -> 2)" depending if caching is used
行为的变化取决于RDD是否被缓存。在Spark API中,有一组函数允许对数据进行变异,文档中明确指出了这一点,请参见此示例


考虑使用地图条目的
RDD[(K,V)]
代替地图,即RDD[map[K,V]]。这将允许使用
flatMap
mapPartitions
以标准方式添加新条目。如果需要,映射表示最终可以通过分组等方式生成。

好的,我开发了一些代码来测试如果RDD中引用的对象被映射器变异会发生什么,我很高兴地报告,如果您使用Python编程,这是不可能的

这是我的测试程序:

从pyspark.sql导入SparkSession
导入时间
计数=5
def funnydir(一):
“”“返回i的目录”“”
返回{“i”:i,
“gen”:0}
def funnymap(d):
“”“获取目录并执行funnymap”“”
d['gen']=d.get('gen',0)+1
d['id']=id(d)
返回d
如果名称=“\uuuuu main\uuuuuuuu”:
spark=SparkSession.builder.getOrCreate()
sc=spark.sparkContext
dfroot=sc.parallelize(范围(计数)).map(funnydir)
dfroot.persist()
df1=dfroot.map(funnymap)
df2=df1.map(funnymap)
df3=df2.map(funnymap)
df4=df3.map(funnymap)
打印(“=============================================================”)
打印(“***df1:”,df1.collect())
打印(“***df2:,df2.collect())
打印(“***df3:,df3.collect())
打印(“***df4:,df4.collect())
打印(“=============================================================”)
ef1=dfroot.map(funnymap)
ef2=ef1.map(funnymap)
ef3=ef2.map(funnymap)
ef4=ef3.map(funnymap)
打印(“***ef1:,ef1.collect())
打印(“***ef2:,ef2.collect())
打印(“***ef3:,ef3.collect())
打印(“***ef4:,ef4.collect())
如果运行此命令,您将看到字典
d
的id在每个数据帧中都是不同的。显然,Spark正在序列化从映射器传递到映射器的对象。所以每一个都有自己的版本


如果这不是真的,那么第一次调用
funnymap
生成df1也会改变
dfroot
数据帧中的生成,因此ef4将具有与df4不同的生成编号。

您能显示代码吗?添加/删除/修改元素是Spark RDD上非常常见的操作,这很容易改变RDD的大小,我找不到为什么Spark会被混淆的原因。@allthenutsandbolts,代码非常复杂。我可以试着给出一个最小的例子,但我们的最小例子不会使spark崩溃。@JiayiLiao,RDD是不变的。可以使用映射将元素添加到RDD。但是map不应该修改其操作的RDD。例如,在foreach()文档中,它说“在foreach()之外修改累加器以外的变量可能会导致未定义的行为”。@vy32您的意思是您已经开发了一个可变RDD类,可以直接修改它,而无需创建新类?