Spark中累加器(Accumulator)使用

18 篇文章 0 订阅
16 篇文章 1 订阅

累加器用来把 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
  }
}
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值