累加器实现原理
累加器是用来把Executor端变量信息聚合到Driver端。在Driver程序中定义的变量,在Executor端的每个Task都会得到这个变量的一份新的副本,每个task更新每个task更新这些副本的值后,传回Driver端进行merge
系统累加器
val rdd = sc.makeRDD(List(1,2,3,4,5))
// 声明累加器
var sum = sc.longAccumulator("sum");
rdd.foreach(
num => {
// 使用累加器
sum.add(num)
}
)
// 获取累加器的值
println("sum = " + sum.value)
自定义累加器
/*
自定义数据累加器:WordCount
1. 继承AccumulatorV2,定义泛型
IN:累加器输入的数据类型
OUT:累加器返回的数据类型
2. 重写方法(6)
*/
class MyAccumulator extends AccumulatorV2[String,mutable.Map[String,Long]]{
private var wcMap = mutable.Map[String,Long]()
override def isZero: Boolean = {
wcMap.isEmpty
}
override def copy(): AccumulatorV2[String, mutable.Map[String, Long]] = {
new MyAccumulator()
}
override def reset(): Unit = {
wcMap.clear()
}
// 获取累加器需要计算的值
override def add(v: String): Unit = {
val newCnt = wcMap.getOrElse(v,0L) + 1
wcMap.update(v,newCnt)
}
// Driver合并多个累加器
override def merge(other: AccumulatorV2[String, mutable.Map[String, Long]]): Unit = {
val map1 = this.wcMap
val map2 = other.value
map2.foreach{
case (word,count) => {
val newCount = map1.getOrElse(word,0L) + count
map1.update(word,newCount)
}
}
}
// 累加器结果
override def value: mutable.Map[String, Long] = {
wcMap
}
}