文章目录

  • 一. 累加器:分布式只写变量
  • 1.实现原理
  • 2. 基础编程
  • 2.1系统累加器
  • 2.2 自定义累加器
  • 二.广播变量:分布式只读变量
  • 1.实现原理
  • 2.基础编程



学完了Spark core三大数据结构之一的RDD,我们继续来看剩下俩

一. 累加器:分布式只写变量

1.实现原理

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

spark累加器特点 spark累加器的原理_spark累加器特点

2. 基础编程

2.1系统累加器

val conf = new SparkConf().setMaster("local[*]").setAppName("test")
    val sc = new SparkContext(conf)
    val rdd = sc.makeRDD(List(1,2,3,4))
    //Spark默认提供了简单数据聚合的累加器
    val sumAcc = sc.longAccumulator("sum")
    //sc.collectionAccumulator
    //sc.doubleAccumulator
    rdd.foreach(num=>{
      sumAcc.add(num)
    })
    println(sumAcc.value)
  }

少加问题:转换算子中调用累加器,如果没有行动算子,那么不会执行
一般情况下累加器放在行动算子中

2.2 自定义累加器

//继承AccumulatorV2
  //定义泛型[in,out],即累加器输入和返回的类型

  class MyAccumulator extends AccumulatorV2[String,mutable.Map[String,Long]]
  {
    private var wcMap = mutable.Map[String,Long]()
    //判断是否为初始状态
    override def isZero: Boolean = {
      wcMap.isEmpty
    }
    //重置累加器
    override def reset(): Unit =
    {
      wcMap.clear()
    }

    //获取累加器需要计算的值
    override def add(word: String): Unit = {
      var newCnt = wcMap.getOrElse(word,0l) + 1
      println(wcMap)
      wcMap.update(word,newCnt)
    }

    //获得值
    override def value: mutable.Map[String,Long] = {this.wcMap}

    override def copy(): AccumulatorV2[String, mutable.Map[String, Long]] = new MyAccumulator

    //合并累加器
    override def merge(other: AccumulatorV2[String, mutable.Map[String, Long]]): Unit =
    {
      val map = other.value
      map.foreach{
        case (word,count)=>
          {
            val newcount = wcMap.getOrElse(word,0l)+count
            map.update(word,newcount)
          }
      }
    }
  }
  object MyAcc {
  def main(args: Array[String]): Unit = {
    val conf = new SparkConf().setMaster("local").setAppName("WordCount")
    val sparkContext = new SparkContext(conf)
    val rdd = sparkContext.makeRDD(List("hello","scala","hello"))

    val myacc = new MyAccumulator
    //向spark容器注册累加器
    sparkContext.register(myacc,"wordCountAcc")

    rdd.foreach(word=>
    {
      myacc.add(word)
    })
    println(myacc.value)
  }
  }

二.广播变量:分布式只读变量

1.实现原理

广播变量用来高效分发较大的对象。向所有工作节点发送一个较大的只读值,以供一个或多个 Spark 操作使用。比如,如果你的应用需要向所有节点发送一个较大的只读查询表,广播变量用起来都很顺手。
在spark中,闭包数据以Task为单位发送,这样可能导致一个Excutor中含有大量重复数据。而广播变量放置在一个Executor中共给各个Task共享,这样就节省了内存空间,由于是共享变量,是不可更改的

2.基础编程

//定义广播变量
 val bc = sparkContext.broadcast(list)
 //获取广播变量
 bc.value