Spark:累加器和局部变量之间的差异

时间:2019-05-09 13:14:44

标签: apache-spark accumulator

在探索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都给出相同的结果。

1 个答案:

答案 0 :(得分:1)

counter是本地变量,可能正在将在驱动程序上执行的本地程序.master("local[3]")中运行。假设您正在运行yarn模式。那么所有逻辑将以分布式方式工作,您的局部变量将不会被更新(因为其局部变量将被更新),但是累加器将被更新。由于其分布变量。假设您有2个执行程序正在运行该程序...一个执行程序将更新,而另一个执行程序可以看到最新值。 在这种情况下,您的cntAccum可以在纱线分布模式下从其他执行者那里获得最新价值。作为局部变量counter不能...

accumulators are read and write. see docs here.

enter image description here

在图像执行程序ID中为localhost。如果您使用的纱线带有2-3个执行者,它将显示执行者ID。希望有帮助。