spark 累加器 ,共享变量

spark中 3大数据结构

  1. RDD : (弹性分布,分布式数据集)
  2. 广播变量 : 分布式的 只读共享变量
  3. 累加器 : 分布式的只写共享变量
 在某些情况下用rdd计算不是很好,所以有了 广播变量和累加器
 
例:
		val ints: RDD[Int] = spark.sparkContext.makeRDD(Array(1, 2, 3, 4), 2)

        var sum = 0

        ints.foreach(x=> {
            sum += x
        })
        
        println(sum)  // 0 
        //解释如下: sum 在 drver 端, 当executor 端 需要用到 driver端的sum 变量是, driver端会发送sum=0到executor,在 executor端 会进行累加计算, 
        //但是累加后的值不会返回给driver端 所以sum端的值还是 0 

在这里插入图片描述

因此需要使用共享变量 (累加器)
		val conf = new SparkConf()
        conf.setMaster("local[*]").setAppName("SessionStepTime01")
        val spark = SparkSession.builder().config(conf).enableHiveSupport().getOrCreate()

        spark.sparkContext.setLogLevel("warn")

        val ints: RDD[Int] = spark.sparkContext.makeRDD(Array(1, 2, 3, 4), 2)

        var sum = 0

        //ints.foreach(x=> {
            sum += x
       // })

       // println(sum)

        val accumulator: LongAccumulator = spark.sparkContext.longAccumulator
        ints.foreach(x=> {
        	//执行累加器累加功能
            accumulator.add(x)
        })
        //获取累加器的值
        sum = accumulator.value
        println(sum ) // 10
自定义累加器使用
import org.apache.spark.util.AccumulatorV2
import scala.collection.mutable

/**
  * 自定义累加器
  */
/**
  * AccumulatorV2 里面需要两个参数 一个输入类型, 一个输出类型
  */
class SessionAggrStatAccumulator extends AccumulatorV2[String, mutable.HashMap[String, Int]] {

  // 保存所有聚合数据  定义输出的对象(返回的对象)
  private val aggrStatMap = mutable.HashMap[String, Int]()

  //单钱你累加器是否为出事状态
  override def isZero: Boolean = {
    aggrStatMap.isEmpty
  }

  //复制累加器状态
  override def copy(): AccumulatorV2[String, mutable.HashMap[String, Int]] = {
    val newAcc = new SessionAggrStatAccumulator
    aggrStatMap.synchronized{
      newAcc.aggrStatMap ++= this.aggrStatMap
    }
    newAcc
  }

  //重置累加器对象
  override def reset(): Unit = {
    aggrStatMap.clear()
  }

  //根据业务逻辑,向累加器中增加数据
  override def add(v: String): Unit = {
    if (!aggrStatMap.contains(v))
      aggrStatMap += (v -> 0)
    aggrStatMap.update(v, aggrStatMap(v) + 1)
  }

  //合并累加器 (不同executor端的数据进行合并 返回driver端)
  override def merge(other: AccumulatorV2[String, mutable.HashMap[String, Int]]): Unit = {
    other match {
      case acc:SessionAggrStatAccumulator => {
        (this.aggrStatMap /: acc.value){ case (map, (k,v)) => map += ( k -> (v + map.getOrElse(k, 0)) )}
      }
    }
  }

  //输出的值
  override def value: mutable.HashMap[String, Int] = {
    this.aggrStatMap
  }
}

	// 设置自定义累加器,实现所有数据的统计功能,注意累加器也是懒执行的
    val sessionAggrStatAccumulator = new SessionAggrStatAccumulator

    // 注册自定义累加器
    sc.register(sessionAggrStatAccumulator, "sessionAggrStatAccumulator")
    //添加值
    sessionAggrStatAccumulator.add("1-2");
    //获取值
    val value: mutable.HashMap[String, Int] = sessionAggrStatAccumulator.value
    
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值