累加器用来把 Executor 端变量信息聚合到 Driver 端。在 Driver 程序中定义的变量,在
Executor 端的每个 Task 都会得到这个变量的一份新的副本,每个 task 更新这些副本的值后,
传回 Driver 端进行 merge。
累加器全称:分布式共享只写变量
分布式:由于Excetor是多个,那么累加器也会复制成多份进行计算
共享:每个Excetor单独使用自己的accumulator,
只写:每个Excetor只能写自己单独的accumulator
如果是单独的变量,而不是累加器,那么每个Excetor都会复制一份这个变量,但是这个变量不会在Excetor执行结束后返回给Driver
所以只会在使用accumulator才能在Excetor执行结束后才返回给Driver
//因为是普通变量,所以它在excetor执行结束后不会返回给Driver
var num: Int = 0
//累加器,从sc中获取,会自动注册到SparkContext中
//默认的累加器有,long,Double,List
var num2=sc.longAccumulator("num2")
val rdd = sc.makeRDD(List(1, 2, 3, 4, 5))
val mapRDD = rdd.map {
case word => {
num += 1
num2.add(1)
word
}
}
mapRDD.foreach(println)
println(num)
println(num2.value)
默认提供的累加器有:
long,double,list
因为累加器是Excetor中出现的,并且如果累加器的逻辑是转换算子中,那么可能出现少加和多加的情况
少加:累加器放在转换算子中,没有 行动算子执行,那么转换算子是不会执行的,这个时候累计器逻辑就不会执行
多加:累加器放在转换算子,如果行动算子执行多次,那么转换RDD的逻辑就会执行多次,会出现多加的情况
object MyAccumulatorTest {
def main(args: Array[String]): Unit = {
val sparkConf = new SparkConf().setMaster("local[*]").setAppName("cachAndPersist")
val sc = new SparkContext(sparkConf)
val rdd = sc.makeRDD(List("hello spark", "hello scala"))
val flatRDD = rdd.flatMap(_.split(" "))
val myAccumulator = new MyAccumulator
sc.register(myAccumulator,"myacc")
val mapRDD = flatRDD.map {
case word => myAccumulator.add(word)
}
mapRDD.collect()
println(myAccumulator.value)
sc.stop()
}
class MyAccumulator extends AccumulatorV2[String,mutable.Map[String,Long]] {
var mapAccumulator:mutable.Map[String,Long]=mutable.Map()
//判断累加器是不是初始值
override def isZero: Boolean = mapAccumulator.isEmpty
//复制累加器
override def copy(): AccumulatorV2[String, mutable.Map[String, Long]] = new MyAccumulator
//清空累加器
override def reset(): Unit = mapAccumulator.clear()
//累加逻辑
override def add(v: String): Unit =mapAccumulator.update(v,mapAccumulator.getOrElse(v, 0L) + 1L)
//合并
override def merge(other: AccumulatorV2[String, mutable.Map[String, Long]]): Unit = {
val value1 = other.value
value1.foreach{
case (k,v)=> mapAccumulator.update(k,mapAccumulator.getOrElse(k,0L)+v)
}
}
//获取最终的值
override def value: mutable.Map[String, Long] = mapAccumulator
}
}