Spark Core -- 广播变量

1、在每一次运行Spark的任务的时候,算子内部的代码最终会被封装到Task中并发送到Executor中

2、但是如果算子内部中需要使用到算子外部的变量,此时就会将外部的变量也封装到Task中,然后再发送到Executor中

        a、此时使用的Task实际上是外部变量的副本

        b、Task的数量决定外部变量的副本数

3、因为Task的数量一定会比Exceutor的数量要多,此时Driver端就会将每一个外部变量广播给每一个Task。这样外部变量的副本的个数会很多,运行效率较低。

4、此时就可以将外部变量广播给每一个Exceutor,因为每一个Task都是在Exceutor上执行的,所以每一个Task会去对应的Exceutor上获取外部变量   

5、广播变量是Exceutor之间共享的变量

6、广播变量在Driver中是一次性创建的,Exceutor对这些变量只能进行读取操作

7、一般会对本地的变量进行广播,例如是List集合、Map集合等。

8、广播变量广播到Executor中是有BlockManager所管理的

9、Executor上运行的Task都可以访问广播变量

    

广播变量获取流程如下:

        1、首先是算子内部使用了广播变量

        2、然后Task会向Executor申请获取广播变量,若Executor暂无数据,则

                Executor首先会向同机架的其他Executor获取

                若获取不到再向跨机架的Executor获取 如果还是获取不到,则

                向Driver端获取数据

        3、广播变量获取后会优先放入内存中,由BlockManager管理维护 后续Task可直接从MemoryStore中获取使用

import org.apache.spark.broadcast.Broadcast
import org.apache.spark.{SparkConf, SparkContext}
import org.apache.spark.rdd.RDD

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

    val conf: SparkConf = new SparkConf()
    conf.setMaster("local")
    conf.setAppName("Demo24MapJoin")
    val sc: SparkContext = new SparkContext(conf)
    val stuRDD: RDD[String] = sc.textFile("spark/data/stu/students.txt")
    val scoRDD: RDD[String] = sc.textFile("spark/data/stu/score.txt")

    //将两张表进行关联,使用Spark中的join会产生shuffle的阶段会比较消耗时间
    val stuRDD01: RDD[(String, String)] = stuRDD.map(kv => (kv.split(",")(0), kv))
    val scoRDD01: RDD[(String, String)] = scoRDD.map(kv => (kv.split(",")(0), kv))
    stuRDD01.join(scoRDD01).foreach(println)


    /**
     * 使用MapJoin:(实际上是对join的一种优化)大表join小表,中间没有shuffle的产生,可以将小表进行广播
     */
    //首先将stuRDD01转化成本地的Map集合,在进行关联,前提也必须是一种kv形式的
    val stuRDDMap: collection.Map[String, String] = stuRDD01.collectAsMap()
    //将表进行关联
    scoRDD01.map(kv=>{
      stuRDDMap.getOrElse(kv._1,"")
    }).foreach(println)



    //第二种:使用广播变量,实现MapJoin,如果算子内部使用到外部的集合,就可以使用广播变量,可以通过调用变量.value在算子内部获取
    val stuRDDMapBro: Broadcast[collection.Map[String, String]] = sc.broadcast(stuRDDMap)
    scoRDD01.map(kv => {
      stuRDDMapBro.value.getOrElse(kv._1, "")
    }).foreach(println)
  }
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值