在探索Spark累加器时,我试图理解并展示Spark中的累加器和常规变量之间的区别。但是输出似乎与我的期望不符。我的意思是,累加器和计数器在程序末尾具有相同的值,并且能够在转换函数内读取累加器(根据文档,只有驱动程序才能读取累加器)。难道我做错了什么?我的理解正确吗?
object Accmulators extends App {
val spark = SparkSession.builder().appName("Accmulators").master("local[3]").getOrCreate()
val cntAccum = spark.sparkContext.longAccumulator("counterAccum")
val file = spark.sparkContext.textFile("resources/InputWithBlank")
var counter = 0
def countBlank(line:String):Array[String]={
val trimmed = line.trim
if(trimmed == "") {
cntAccum.add(1)
cntAccum.value //reading accumulator
counter += 1
}
return line.split(" ")
}
file.flatMap(line => countBlank(line)).collect()
println(cntAccum.value)
println(counter)
}
输入文件中的文本之间有9个空行
4) Aggregations and Joins
5) Spark SQL
6) Spark App tuning
输出:
计数器和cntAccum都给出相同的结果。
答案 0 :(得分:1)
counter
是本地变量,可能正在将在驱动程序上执行的本地程序.master("local[3]")
中运行。假设您正在运行yarn
模式。那么所有逻辑将以分布式方式工作,您的局部变量将不会被更新(因为其局部变量将被更新),但是累加器将被更新。由于其分布变量。假设您有2个执行程序正在运行该程序...一个执行程序将更新,而另一个执行程序可以看到最新值。
在这种情况下,您的cntAccum
可以在纱线分布模式下从其他执行者那里获得最新价值。作为局部变量counter
不能...
自accumulators are read and write. see docs here.
在图像执行程序ID中为localhost。如果您使用的纱线带有2-3个执行者,它将显示执行者ID。希望有帮助。