2015-09-06 53 views
6

Spark RDD以不可变,容错和弹性方式构建。会有什么情况,Spark RDD无法满足不变性?

RDD在所有情况下是否满足不变性?或者是否有任何情况,无论是Streaming还是Core,RDD可能无法满足不变性?

+0

不,它永远不会失败!如果底层基础设施是不可变的,那么你希望它不能满足不变性? – eliasah

+0

是的,我同意这个结构是不可变的。我只是想检查是否有任何情况。它也具有弹性和容错能力,允许在失败时重新计算。重新计算是否也确保了不变性?考虑,在流式传输窗口中工作并创建一个dstream,这是一组RDD,意味着失败和重新计算,它是否保证不变性。 – Srini

回答

0

拿这个例子:

sc.makeRDD(1 to 100000).map(x=>{ 
    println(x) 
    x + 1 
}.collect 

如果map完成后一个节点发生故障,但完整的结果还没有被发送回驱动,然后是map将重新计算在不同的机器上。最终结果将始终保持不变,因为任何计算的双倍计算值只会被返回一次。但是,对于某些呼叫,println将发生两次。所以,是的,DAG本身的不变性是有保证的,但是你仍然必须假设你的代码会运行多次。

4

这要看你在谈论RDD时的意思。严格地说,RDD只是描述了只存在于驱动程序中的血统,并没有提供任何可用于变异血统的方法。

当处理数据时,我们不能再谈论RDD,但仍然使用不可变数据结构暴露数据(斯卡拉的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 

您可以根据需要多次执行此操作并获得相同的结果。现在,让我们cacherdd和重复整个过程:

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)。