累加器是用于跟踪和调试的技术, 在driver如果需要获取executor的执行结果,可以使用累加器机制。
executor端使用累加器的add方法将结果回传给driver,driver能够进行累计处理。
executor端只能调用add方法,不要访问value.
以下为自定义累加器, 通过累加器实现气温数据的双聚合(max|min)。
import org.apache.spark.util.AccumulatorV2
import org.apache.spark.{SparkConf, SparkContext}
import scala.collection.mutable.{Map=>MMap}
/**
* Created by Administrator on 2019-7-6.
*/
object AccDemo {
def main(args: Array[String]) {
val conf=new SparkConf()
conf.setAppName("AccDemo")
conf.setMaster("local[*]")
val sc=new SparkContext(conf)
val myaccc=new MyAcc()
sc.register(myaccc,"myaccc")
val rdd1=sc.textFile("file:///g:/temp.txt",3)
val rdd2=rdd1.map(line=>{
val arr=line.split(" ")
(arr(0).toInt,arr(1).toInt)
})
rdd2.foreach(t=>{
myaccc.add(t)
})
val __value=myaccc.value
__value.toList.sortBy(_._1).foreach(println)
}
/**
* 自定义累加器
*/
class MyAcc extends AccumulatorV2[(Int,Int),MMap[Int,(Int,Int)]](){
//定义map集合
var _value: MMap[Int,(Int,Int)]=MMap[Int,(Int,Int)]()
//判断是否为空
override def isZero: Boolean = _value.isEmpty
//合并两个累加器
override def merge(other: AccumulatorV2[(Int, Int), MMap[Int, (Int, Int)]]): Unit = {
for((k,t) <- other.value){
val oyear=k
val omax=t._1
val omin=t._2
val myvalue=_value.getOrElse(oyear,(omax,omin))
_value.put(oyear,(Math.max(omax,myvalue._1),Math.min(omin,myvalue._2)))
}
}
override def copy(): AccumulatorV2[(Int, Int), MMap[Int, (Int, Int)]] = {
val newAcc = new MyAcc()
newAcc._value=_value
newAcc
}
//重置
override def reset(): Unit = {
_value.clear()
}
override def value: MMap[Int, (Int, Int)] =_value
override def add(v: (Int, Int)): Unit = {
val year=v._1
val temp=v._2
val oldValue=_value.getOrElse(year,(temp,temp))
_value.put(year,(Math.max(temp,oldValue._1),Math.min(temp,oldValue._2)))
}
}
}
测试数据放在文件里使用:
1959 23
1960 28
1926 19
1996 33
1921 11
1941 -24
1966 4
1909 -12
1940 38
1901 10
1995 50
1980 -46
1944 -35
1993 -14
1959 22
1907 2
1926 28
1961 -30
1902 48
1941 32
1989 44
1957 -7
1954 -7
1988 -29
1924 31
1972 -27
1950 -41
1960 5
1937 38
1917 20
1972 29
1967 48
1907 2
1937 40
1992 38