首先,看下以下代码:
var value = 0
sc.parallelize(1 to 10).foreach(i=>value += i)
value
这里value的结果仍然为0
这个比较好解释:
因为 i => value += i 这个Function在运算之前需要经历:序列化 --> broadcase --> 被Executor获取 --> 反序列化 --> 调用 等一系列过程,最终执行 value += i操作的是Executor进程中的value变量,虽然这个变量来自于Driver的value,但经历了序列化、网络传输等一系列操作之后已经是运行在不同进程中的两个完全不同的变量了,所以这里在Executor对value进行累加,并不会影响Driver中value的值
下面,再看看累加器的使用
val accum = sc.accumulator(0)
sc.parallelize(1 to 10).foreach(i=>accum += i)
accum.value
对于累加器我开始也比较疑惑:
为什么使用了Spark提供了Accumulator API就可以实现累加了呢?accum 在Executor中进行累加是如何改变Driver中accu的值的?
翻看了源码之后才发现,背后做了很多工作:
首先,看看Driver端的accumulator究竟是何时进行累加的?