Spark RDD以不可变,容错和弹性的方式构建。
RDD是否满足所有情况下的不变性?或者有任何情况,无论是在流媒体还是核心,RDD可能无法满足不变性?
答案 0 :(得分:4)
这取决于你谈论RDD
时的意思。严格地说RDD
只是对仅存在于驱动程序上的血统的描述,并且它没有提供任何可用于改变其血统的方法。
当处理数据时,我们不再谈论RDD,但是使用不可变数据结构(Scala中的scala.collection.Iterator
,Python中的itertools.chain
)公开了数据。
到目前为止一切顺利。遗憾的是,数据结构的不变性并不意味着存储数据的不变性。让我们创建一个小例子来说明:
val rdd = sc.parallelize(Array(0) :: Array(0) :: Array(0) :: Nil)
rdd.map(a => { a(0) +=1; a.head }).sum
// Double = 3.0
您可以根据需要多次执行此操作并获得相同的结果。现在,让cache
rdd
重复整个过程:
rdd.cache
rdd.map(a => { a(0) +=1; a.head }).sum
// Double = 3.0
rdd.map(a => { a(0) +=1; a.head }).sum
// Double = 6.0
rdd.map(a => { a(0) +=1; a.head }).sum
// Double = 9.0
由于我们在第一个map
中使用的函数不是纯粹的,并且在适当的位置修改了它的可变参数,这些更改会在每次执行时累积并导致不可预测的输出。例如,如果从缓存中逐出rdd
,我们可以再次获得3.0。如果某些分区未缓存,则可能会出现混合结果。
PySpark提供更强的隔离并获得结果,这是不可能的,但这是建筑问题而不是不变性。
此处带走的信息是,在处理可变数据时应格外小心并避免任何修改,除非明确允许(fold
,aggregate
)。
答案 1 :(得分:0)
举个例子:
sc.makeRDD(1 to 100000).map(x=>{
println(x)
x + 1
}.collect
如果节点在map
完成后失败,但尚未将完整结果发送回驱动程序,则map
将在另一台计算机上重新计算。最终结果将始终相同,因为任何双倍计算的值将仅返回一次。但是,对于某些调用,println
将发生两次。所以,是的,DAG本身的不变性是有保证的,但你仍然必须编写代码,假设它将运行多次。