Spark--累加器

累加器

  • 累加器
    • 1.实现原理
    • 2.系统累加器
    • 3.自定义累加器

累加器

Spark 计算框架为了能够进行高并发和高吞吐的数据处理,封装了三大数据结构,用于处理不同的应用场景。三大数据结构分别是:

  • RDD : 弹性分布式数据集
  • 累加器:分布式共享只写变量
  • 广播变量:分布式共享只读变量

1.实现原理

累加器用来把Executor 端变量信息聚合到Driver 端。在Driver 程序中定义的变量,在Executor 端的每个Task 都会得到这个变量的一份新的副本,每个 task 更新这些副本的值后, 传回Driver 端进行 merge。

2.系统累加器

object Spark_rdd_01 {
  def main(args: Array[String]): Unit = {
    val conf = new SparkConf().setAppName("RDD").setMaster("local[*]")
    val sc = new SparkContext(conf)
    val rdd: RDD[Int] = sc.makeRDD(List(1,2,3,4))

    //获取系统累加器
    //Spark默认就提供了简单数据聚合的累加器
    val sum: LongAccumulator = sc.longAccumulator("sum")
    val value: RDD[Int] = rdd.map(num => {
      //使用累加器
      sum.add(num)
      num
    })
    //获取累加器的值
    //少加:转换算子中调用累加器,如果没有行动算子,那么不会执行
    //多加:转换算子调用累加器,执行一次行动算子,累加器就会更新一次
    //一般情况下,累加器会放置在行动算子中进行操作
    println(sum.value)
    println("------------")
    value.collect()
    println(sum.value)
    println("------------")
    value.collect()
    println(sum.value)

    sc.stop()
  }
}
0
------------
10
------------
20

3.自定义累加器

实现wordcount

object Spark_rdd_01 {
  def main(args: Array[String]): Unit = {
    val conf = new SparkConf().setAppName("RDD").setMaster("local[*]")
    val sc = new SparkContext(conf)
    val rdd: RDD[String] = sc.makeRDD(List("hello","spark","hello"))

    //创建累加器对象
    val acc = new Accumulate
    //向spark进行注册
    sc.register(acc,"wordcount")

    //遍历
    rdd.foreach(word=>{
      //数据的累加,使用累加器
      acc.add(word)
    })

    //获取累加器累加的结果
    println(acc.value)
    

    sc.stop()
  }
  /*
  自定义数据累加器
  实现的功能:wordcount
  继承AccumulatorV2
  AccumulatorV2两个参数,IN和OUT
  IN:累加器输入的数据类型
  OUT:累加器返回的数据类型
   */

  class Accumulate extends AccumulatorV2[String,mutable.Map[String,Long]]{
    //新建一个空集合来接受累加器的值
    private var accMap=mutable.Map[String,Long]()

    //判断是否是初始状态
    override def isZero: Boolean = {
      accMap.isEmpty

    }

    //复制一个新累加器
    override def copy(): AccumulatorV2[String, mutable.Map[String, Long]] = {
      new Accumulate
    }

    //重置累加器,就是把集合里的数据清空
    override def reset(): Unit = {
      accMap.clear()

    }

    //获取累加器需要计算的值
    override def add(word: String): Unit = {
      //判断集合是否有这个单词
      //如果有数量加1,表示当前出现一次,得到新的总数
      //如果没有找到这个单词,默认数量为0再加1
      //接下来集合的数据更新一下
      val newcount: Long = accMap.getOrElse(word,0L)+1
      accMap.update(word,newcount)

    }

    //Driver合并累加器操作
    //相当于两个map的合并
    override def merge(other: AccumulatorV2[String, mutable.Map[String, Long]]): Unit = {
      var map1=this.accMap
      var map2=other.value
      map2.foreach{
        case (word,count)=>
       val newCount: Long = map1.getOrElse(word,0L)+count
          map1.update(word,newCount)
      }
    }

    //累加器结果
    override def value: mutable.Map[String, Long] = {
      accMap
    }
  }
}
Map(spark -> 1, hello -> 2)

你可能感兴趣的:(Scala&Spark,spark,scala,big,data)