Spark的三大核心数据结构:RDD、累加器(只写不读)、广播变量(只读不写)
在spark应用程序中,我们经常会有这样的需求,如异常监控,调试,记录符合某特性的数据的数目,这种需求都需要用到计数器,如果一个变量不被声明为一个累加器,那么它将在被改变时不会再driver端进行全局汇总,即在分布式运行时每个task运行的只是原始变量的一个副本,并不能改变原始变量的值,但是当这个变量被声明为累加器后,该变量就会有分布式计数的功能。
来个简单的例子,看为什么要使用累加器
object Acc {
def main(args: Array[String]): Unit = {
val sparConf = new SparkConf().setMaster("local").setAppName("Acc")
val sc = new SparkContext(sparConf)
val rdd = sc.makeRDD(List(1, 2, 3, 4))
var sum = 0
rdd.foreach(
num => {
sum += num
}
)
println("sum = " + sum)
sc.stop()
}
}
sum = 0
Process finished with exit code 0
累加器用来把 Executor 端变量信息聚合到 Driver 端。在 Driver 程序中定义的变量,在Executor 端的每个 Task 都会得到这个变量的一份新的副本,每个 task 更新这些副本的值后,传回 Driver 端进行 merge。
使用累加器后:
object Acc {
def main(args: Array[String]): Unit = {
val sparConf = new SparkConf().setMaster("local").setAppName("Acc")
val sc = new SparkContext(sparConf)
val rdd = sc.makeRDD(List(1, 2, 3, 4))
val sumAcc = sc.longAccumulator("sum")
rdd.foreach(
num => {
sumAcc.add(num)
}
)
println(sumAcc.value)
sc.stop()
}
}
sum = 10
Process finished with exit code 0