i+=1在Excutor端执行,var i = 0和println(i)在Driver端执行。collect算子虽然能够回收结果,但是并不代表它啥都能回收。所以打印出来的依旧是Driver端定义的i。
错误代码:
//打印出来的总是0
val session = SparkSession.builder().appName("broadcast").master("local").getOrCreate()
val sc = session.sparkContext
val lines = sc.textFile("data/words")
var i=0;
val rdd = lines.map(one => {
i += 1
one
})
rdd.collect()
println(i)
于是就有了累加器,在计算结束之后,把各个分区的计算结果收集一下到Driver端,再做累加。累加器在Driver端定义、初始化,在Executor端更新(1.6版本在Executor不能accumulator.value获取累加器的值)。
定义累加器:
val accumulator = sc.longAccumulator
通过累加器,就能够收集到Executor分区的计算结果到Driver端,并累加。
完整代码如下:
val session = SparkSession.builder().appName("broadcast").master("local").getOrCreate()
val sc = session.sparkContext
val accumulator = sc.longAccumulator
val lines = sc.textFile("data/words")
var i=0;
val rdd = lines.map(one => {
// i += 1
accumulator.add(1)
println(accumulator)
one
})
rdd.collect()
println(accumulator.value)