第五章_Spark核心编程_累加器
1. 什么是累加器
累加器是用来把Executor端的变量信息聚合到Driver端
2. 累加器实现原理
* 在Driver程序中定义的变量,在Executor端的每个Task节点上都会复制这个变量的副本
* ,每个Task节点更新这些副本的值后,再传回Driver端进行merge
3. 怎样获取累加器?
* 1. 系统自带累加器 * long类型累加器 * def longAccumulator: LongAccumulator * def longAccumulator(name: String): LongAccumulator * double类型累加器 * def doubleAccumulator: DoubleAccumulator * def doubleAccumulator(name: String): DoubleAccumulator * collect类型累加器 * def collectionAccumulator[T]: CollectionAccumulator[T] * def collectionAccumulator[T](name: String): CollectionAccumulator[T] * * 2. 自定义累加器
4.怎样实现自定义累加器?
* 1.继承AccumulatorV2,定义泛型 * abstract class AccumulatorV2[IN, OUT] * IN : 累加器输入的数据类型(一般为要累加Rdd的元素类型) * OUT : 累加器返回的数据类型 * 2.重新方法
5. 示例(spark 自带累加器)
/*spark 自带累加器*/ object accTest { def main(args: Array[String]): Unit = { val sparkconf: SparkConf = new SparkConf().setMaster("local").setAppName("distinctTest") val sc: SparkContext = new SparkContext(sparkconf) val rdd1 = sc.makeRDD(List(1, 2, 3, 4, 5, 6, 7, 8, 9), 3) //普通变量 var sum: Int = 0 //初始化 系统累加器 val accSumLong: LongAccumulator = sc.longAccumulator("sumAcc-long") val accSumdouble: DoubleAccumulator = sc.doubleAccumulator("sumAcc-double") val accSumcollect: CollectionAccumulator[Int] = sc.collectionAccumulator("sumAcc-collect") //对变量进行累加 rdd1.foreach(sum += _) //使用累加器对元素进行累加 rdd1.foreach(accSumLong.add(_)) rdd1.foreach(accSumdouble.add(_)) rdd1.foreach(accSumcollect.add(_)) //查看累加结果 println(s"sum:${sum}") //获取累加器的value println(s"LongAccumulator:${accSumLong.name} - ${accSumLong.value}") println(s"LongAccumulator:${accSumdouble.name} - ${accSumdouble.value}") println(s"LongAccumulator:${accSumcollect.name} - ${accSumcollect.value}") sc.stop() } }
6.示例(spark 自定义累加器)
/*spark 使用自定义累加器-实现wordcount*/ object custAccTest { def main(args: Array[String]): Unit = { val sparkconf: SparkConf = new SparkConf().setMaster("local").setAppName("distinctTest") val sc: SparkContext = new SparkContext(sparkconf) val rdd = sc.textFile("Spark_319/src/data/*.txt") val rdd1 = rdd.flatMap(_.split(" ")) //使用自定义累加器 //向环境中注册累加器 val acc = new custAccumulator sc.register(acc, "自定义累加器") //使用累加器对元素进行累加 rdd1.foreach(acc.add(_)) //获取累加器的value println(s"custAccumulator:${acc.name} - ${acc.value}") sc.stop() } } /*spark 自定义累加器*/ /* * 需求 : 自定义累加器,实现 wordcount功能 * 1.继承 AccumulatorV2抽象类 * 2.初始化 map,利用map实现词频统计 * */ class custAccumulator extends AccumulatorV2[String, mutable.Map[String, Long]] { /*定义 可变map*/ var map: mutable.Map[String, Long] = mutable.Map() /*判断 累加器是否为初始状态*/ override def isZero: Boolean = map.isEmpty //为当前累加器创建一个 新副本 //发送到不同的task节点 override def copy(): AccumulatorV2[String, mutable.Map[String, Long]] = new custAccumulator //重置累加器(清空累加器) override def reset(): Unit = map.clear() //获取数据并进行累加 //根据指定的规则,向累加器中添加元素 override def add(word: String): Unit = { /*添加规则 * 1.查询map中是否存在key=word * 如果存在则 * (key,value+1) * 如果不存在则 * (key,1 * */ val newCnt: Long = map.getOrElse(word, 0L) + 1 map.update(word, newCnt) } //合并累加器 override def merge(other: AccumulatorV2[String, mutable.Map[String, Long]]): Unit = { var map1 = this.map var map2 = other.value //merge-in-place map = map1.foldLeft(map2)( (innerMap, kv) => { innerMap(kv._1) = innerMap.getOrElse(kv._1, 0L) + kv._2 innerMap } ) } //返回当前累加器结果 override def value: mutable.Map[String, Long] = map }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 地球OL攻略 —— 某应届生求职总结
· 提示词工程——AI应用必不可少的技术
· 字符编码:从基础到乱码解决
· SpringCloud带你走进微服务的世界