Spark中的累加器和广播变量

本文介绍了Spark中累加器和广播变量的概念与使用。累加器允许在Executor端修改Driver端的变量,常用于计数等操作。广播变量则可以将Driver端的数据高效地发送到Executor中,减少网络传输开销,适用于数据过滤等场景。通过实例展示了累加器计算执行次数和广播变量筛选学生ID的过程,强调了两者在数据共享和更新上的区别。
摘要由CSDN通过智能技术生成

累加器

用来修改Executor端取不到的一些值

我们这里做一个计算,来计算这里foreach了多少次,按照我们传统的思维,这里我们是可以计算出结果是1000次的,也就是有1000个学生,但我们看到结果并非如此

def main(args: Array[String]): Unit = {
    val conf: SparkConf = new SparkConf()
      .setMaster("local")
      .setAppName("Demo16Cache")

    val sc: SparkContext = new SparkContext(conf)

    val stuRDD: RDD[String] = sc.textFile("D:\\BigDaTa\\JAVA_Project\\ShuJia01\\data\\students.txt")

    var i:Int = 0
    println("i is " + i)
    stuRDD.foreach(line=>{
      i += 1
      println(line)
    })
    println("i is " + i)

我们可以看到这里面的结果,两个i都是0,这是为什么呢
在这里插入图片描述
我们把这里的代码拿出来单独做一个分析
这里一段代码是在Driver端的JVM中运行的,一段代码是在Executor端的JVM中运行的,所以我们最后的代码是0
在这里插入图片描述
这时候我们非要做一个累加操作,就需要用一个累加器

也就是算子内部的代码要使用外部的变量

val conf: SparkConf = new SparkConf()
      .setMaster("local")
      .setAppName("Demo16Cache")

    val sc: SparkContext = new SparkContext(conf)

    //在Driver端通过累加器创建一个变量l
    //可以当成long类型
    val l: LongAccumulator = sc.longAccumulator

    val stuRDD: RDD[String] = sc.textFile("D:\\BigDaTa\\JAVA_Project\\ShuJia01\\data\\students.txt")

    println("l is " + l.value)
    stuRDD.foreach(line=>{
      //在算子内部使用累加器进行累加
      l.add(1)
    })
    //在Driver端获取累加器的最终结果
    println("l is " + l.value)

算子内部进行累加,算子外部计算出结果
这里我们可以看到结果已经被算出来了
在这里插入图片描述

广播变量

将数据发送到executor中,而不是task中
这里我们根据学号筛选出一部分学生

def main(args: Array[String]): Unit = {
    val conf: SparkConf = new SparkConf()
      .setMaster("local")
      .setAppName("Demo10Broadcast")

    val sc: SparkContext = new SparkContext(conf)
    val stuRDD: RDD[String] = sc.textFile("D:\\BigDaTa\\JAVA_Project\\ShuJia01\\data\\students.txt")

    val stuIDs = List("1500100001","1500100011","1500100021","1500100031")

    stuRDD.filter(stu=>{
      val id: String = stu.split(",")(0)
      stuIDs.contains(id)
    })foreach(println)
  }

可以看到结果顺利的出来了
在这里插入图片描述
我们再去仔细的分析这段代码
在这里插入图片描述
这里我们可以看到,被发送到executor中执行的代码里,包含了stuIDs这个List,而每一个task任务都包含着一个List,那我们这里就需要拿取很多次的List,再发送到executor中,需要网络传输,这样就会十分的浪费资源,于是我们可以使用spark中的广播变量
我们只需要将一份我们需要的Driver端的数据放到Executor中即可,在Executor中的每一个task都能找到这份数据

使用广播变量

val conf: SparkConf = new SparkConf()
      .setMaster("local")
      .setAppName("Demo10Broadcast")

    val sc: SparkContext = new SparkContext(conf)

    val stuRDD: RDD[String] = sc.textFile("D:\\BigDaTa\\JAVA_Project\\ShuJia01\\data\\students.txt")


    val stuIDs = List("1500100001","1500100011","1500100021","1500100031")

    //在driver端将stuIDs广播到每一个executor中
    val stuIDsBro: Broadcast[List[String]] = sc.broadcast(stuIDs)

//    stuRDD.filter(stu=>{
//      val id: String = stu.split(",")(0)
//      stuIDs.contains(id)
//    })foreach(println)

    stuRDD.filter(stu=>{
      val strings: Array[String] = stu.split(",")
      val id: String = strings(0)
      val stuIDsV: List[String] = stuIDsBro.value
      stuIDsV.contains(id)
    })foreach(println)

总结

累加器和广播变量的区别在于
累加器可以获取到Driver端的数据,并且做一个更改
广播变量可以获取到Driver端的数据发送到executor中,只是拿来使用,并不对Driver的数据做一个更改

感谢阅读,我是啊帅和和,一位大数据专业大四学生,祝你快乐。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

啊帅和和。

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值