RDD优化--RDD共享变量(广播变量与累加器)

1、简介

在Spark中,提供了两种类型的共享变量:广播变量 (broadcast variable)与累加器 (accumulator) :

  • 广播变量:主要用于在节点间高效分发大对象。
  • 累加器:用来对信息进行聚合,主要用于累计计数等场景;

2、广播变量

广播变量:允许开发者将一个只读变量(Driver端)缓存到每个节点(Executor)上,而不是每个任务传递一个副本。

每个 Task 任务的闭包都会持有自由变量的副本,如果变量很大且 Task 任务很多的情况下,这必然会对网络 IO 造成压力,为了解决这个情况,Spark 提供了广播变量。

广播变量的做法很简单:就是不把副本变量分发到每个 Task 中,而是将其分发到每个 Executor,Executor 中的所有 Task 共享一个副本变量。

// 把一个数组定义为一个广播变量
val broadcastVar = sc.broadcast(Array(1, 2, 3, 4, 5))
// 之后用到该数组时应优先使用广播变量,而不是原值
sc.parallelize(broadcastVar.value).map(_ * 10).collect()  //访问方式:broadcastVar.value 

注意事项:

  • 1、Driver端变量在每个Executor每个Task保存一个变量副本
  • 2、Driver端广播变量在每个Executor只保存一个变量副本
import org.apache.spark.{SparkConf, SparkContext}

object BroadcastDemo {
  def main(args: Array[String]): Unit = {
    val conf = new SparkConf().setMaster("local[1]").setAppName("BroadcastDemo")
    val sc = SparkContext.getOrCreate(conf)
    //广播
    val arr = Array("hello","hi","good afternoon")
    val hei = sc.broadcast(arr)

    val rdd1 = sc.parallelize(List((1,"zhangsan"),(2,"lisi"),(3,"wangwu")))
    val rdd2 = rdd1.mapValues(x => {
      //使用时才传给worker
      /*println(x)
      println(arr.toString())
      arr(0) + ":" + x*/

      //广播变量,提前说
      println(hei.value.toList)
      hei.value(0) + ":" + x
    })
    rdd2.foreach(println)
  }
}
/*输出:
List(hello, hi, good afternoon)
(1,hello:zhangsan)
List(hello, hi, good afternoon)
(2,hello:lisi)
List(hello, hi, good afternoon)
(3,hello:wangwu)
*/

3、累加器

原理:将每个副本变量的最终值传回 Driver,由 Driver 聚合后得到最终值,并更新原始变量。

只允许added操作,常用于实现计数。

import org.apache.spark.{SparkConf, SparkContext}

object AccumulatorDemo {
  def main(args: Array[String]): Unit = {
    val conf = new SparkConf().setMaster("local[2]").setAppName("AccumulatorDemo")
    val sc = SparkContext.getOrCreate(conf)

    val accum = sc.accumulator(0,"aaa") //第一个参数:初始值  第二个参数:name

    sc.parallelize(Array(1,2,3,4)).foreach(x=>{accum+=x;accum})
    println(accum.value)

    //拓展:glom  打印分区
    val rdd1 = sc.makeRDD(List(1,2,3,4))
    rdd1.glom().collect().foreach(x=>println(x.toList))
  }
}
/*输出:
10
List(1, 2)
List(3, 4)
*/
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值