var cnt = 0
val newRDD = oldRDD.map({ list =>
...some work
cnt = cnt + 1
println(cnt) // print 1, 2, 3.. well
newList // will store in new RDD
})
//out side of map
println(cnt) // It's 0. Why?
作为日志,首先打印地图内部,然后打印出地图的一面。为什么不存储cnt值?
答案 0 :(得分:4)
Spark变换应该是纯函数 - 接收输入,产生输出,没有改变状态或具有任何副作用。你的例子违反了这些。
这里发生的是:
map
的匿名函数序列化并发送给工作人员 cnt
的初始值用它序列化cnt
在每个工作人员反序列化时为0 cnt
cnt
值保持不变作为替代方案,您可以使用Spark的Accumulators来实现这些类型的"计数器"。
答案 1 :(得分:2)
在Spark框架中,当您在闭包中使用外部变量时,它会自动发送到工作节点。每个任务都获得一个变量的新副本,但是如果你更新任务中的变量(这就是你的代码会发生什么),框架就不会发回它并将它与程序的其余部分同步,因为它也是这样做很贵。
如果您在闭包中使用外部变量,则可以将其视为只读变量。
如果你要计算你映射的元素数量,你可以首先使用oldRDD.count()
/ newRDD.count()
(因为看起来你没有过滤元素,它应该给出相同的结果)。
答案 2 :(得分:1)
我认为你应该首先检查一下,以了解Spark中的共享变量:http://spark.apache.org/docs/latest/programming-guide.html#shared-variables