[ Spark ] 累加器.广播变量

累加器

原理

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

image-20220613222659798

系统累加器

累加器的少加/多加问题在于转换算子没有/多次执行

object Spark03_Acc {
  def main(args: Array[String]): Unit = {

    val sparkConf = new SparkConf().setMaster("local[4]").setAppName("acc")
    val sc = new SparkContext(sparkConf)

    val rdd = sc.makeRDD(List(1, 2, 3, 4))

//    println(rdd.reduce(_ + _))
    val sum = sc.longAccumulator("sum")

    //少加
    /*rdd.map(num=>{
      sum.add(num)
    })*/

    val mapRDD = rdd.map(num => {
      sum.add(num)
    })

    mapRDD.collect()
    //多加
    mapRDD.collect()

    println("sum="+sum.value)

    sc.stop()
  }
}

自定义累加器

  1. 继承AccumulatorV2,并设定泛型

  2. 重写累加器的抽象方法

object Spark04_Acc {
  def main(args: Array[String]): Unit = {

    val sparkConf = new SparkConf().setMaster("local[4]").setAppName("acc")
    val sc = new SparkContext(sparkConf)

    val rdd = sc.makeRDD(List("hello","spark","hello"))

    val wcAcc = new MyAccumulator
    sc.register(wcAcc,"wordCountAcc")

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

    sc.stop()
  }
}

class MyAccumulator extends AccumulatorV2[String,mutable.Map[String,Long]]{

  private val wcMap: mutable.Map[String, Long] = mutable.Map[String, Long]()

  override def isZero: Boolean = wcMap.isEmpty

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

  override def reset(): Unit = wcMap.clear()

  override def add(v: String): Unit = {
    val count = wcMap.getOrElse(v, 0L) + 1
    wcMap.update(v,count)
  }

  override def merge(other: AccumulatorV2[String, mutable.Map[String, Long]]): Unit = {
     other.value.foreach{case(w,c)=>{
       val newCount = wcMap.getOrElse(w,0L)+c
       wcMap.update(w,newCount)
     }}
  }

  override def value: mutable.Map[String, Long] = wcMap
}

广播变量

​ 在多个并行操作中使用同一个变量,但是 Spark会为每个任务分别发送。

​ 广播变量用来高效分发较大的对象。向所有工作节点发送一个较大的只读值,以供一个或多个Spark操作使用。

//使用广播变量模拟join
object Spark06_Bc {
  def main(args: Array[String]): Unit = {

    val sparkConf = new SparkConf().setMaster("local[4]").setAppName("acc")
    val sc = new SparkContext(sparkConf)

    val rdd1 = sc.makeRDD(List(
      ("a", 1), ("b", 2), ("c", 3)
    ))

    /*val rdd2 = sc.makeRDD(List(
      ("a", 4), ("b", 5), ("c", 6)
    ))
    val joinRDD = rdd1.join(rdd2)*/

    val map = mutable.Map(("a", 4), ("b", 5), ("c", 6))
    val bc: Broadcast[mutable.Map[String, Int]] = sc.broadcast(map)

    rdd1.map{
      case (w,c)=>{
        //访问广播变量
        val i = bc.value.getOrElse(w, 0)
        (w,(c,i))
      }
    }.collect().foreach(println)

    sc.stop()
  }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值