8.共享变量

共享变量背景:

广播变量

   def main(args: Array[String]): Unit = {
        val conf = new SparkConf()
            .setAppName(s"${_01SparkBroadcastOps.getClass.getSimpleName}")
            .setMaster("local[2]")
        val sc = new SparkContext(conf)

        val provinces = Map[String, String](
            "62" -> "甘肃",
            "34" -> "安徽",
            "14" -> "山西",
            "44" -> "湖南"
        )

        val cities = Map[String, (String, String)](
            "05" -> ("天水", "62"),
            "20" -> ("淮北", "34"),
            "36" -> ("太原", "14"),
            "25" -> ("韶山", "44")
        )

        //rdd
        val stues = List(
            "1 米鼎 18 1 62 05",
            "2 荆波 19 0 34 20",
            "3 穆书岳 23 0 14 36",
            "4 程旋宇 17 1 44 25"
        )

        val stuRDD = sc.parallelize(stues)

        //此时的关联操作,可以通过的广播变量的操作来避免shuffle的操作

        val student = stuRDD.map(line => {
            val fields = line.split("\\s+")
            Student(fields(0), fields(1), fields(2).toInt, fields(3).toInt, fields(4), fields(5))
        })
        println("======================使用广播变量的方式==============================")
        //创建广播变量
        val pBC:Broadcast[Map[String, String]] = sc.broadcast(provinces)
        val cBC:Broadcast[Map[String, (String, String)]] = sc.broadcast(cities)

        student.map(stu => {
            val province = pBC.value(stu.pid)//获取广播变量,并完成字段的映射-->join
            val city = cBC.value(stu.cid)._1
            s"${stu.id}\t${stu.name}\t${stu.gender}\t${province}\t${city}"
        }).foreach(println) //map 的join

        sc.stop()
    }
}
case class Student(id:String, name:String, age:Int, gender:Int, pid:String, cid:String)



累加器

累加器,spark中称之为Accumulator,其作用和MR中的Counter计数器的作用相同,就是记录在计算过程中的某一些值出现的次数,比如,我们在执行wordcount或者任意计算的过程,额外地统计某个单词hello出现多少次。
此时就可以使用Accumulator累加器来完成,主要的程序不方便计算的某些值,同时可以减少一次job作业的提交,一定程度上提升了spark作业的执行效率。

注意:要想让累加器执行,必须要有action的触发,所以累加器的调用只能在一个action之后;需要注意累加器被多次调用产生的数据重复累加的问题。

object _02SparkAccumuatorOps {
    def main(args: Array[String]): Unit = {
        val conf = new SparkConf()
            .setAppName(s"${_02SparkAccumuatorOps.getClass.getSimpleName}")
            .setMaster("local[2]")
        val sc = new SparkContext(conf)

        val list = List(
            "hello you",
            "i hate you",
            "i miss you",
            "i love you",
            "fuck you"
        )

        val words = sc.parallelize(list).flatMap(_.split("\\s+"))

        /**
          * //求多个word,you,i
          * 为了完成上述操作,需要在原始操作基础之上,额外的提交一个spark作业
          * 就需要额外的分配一批资源,就有可能有数据在网络中进行传输
          * 效率不会特别高
          * 此时就有这个一个共享变量——累加器
          */

//        words.filter(word => word == "hello").count()
//        val ab = Array("hello", "i", "you")
//        words.filter(word => ab.contains(word)).map((_, 1)).reduceByKey(_+_)

        //在计算words的过程中统计you出现了多少次
        //创建累加器 选择无参版本,我们无法再sparkUI上面观察到相关的累加器的值
        val acc = sc.longAccumulator("helloAcc")
        val pairs = words.map(word => {
            if(word == "you") {
                acc.add(1)
            }
            (word, 1)
        })
        println("you出现的次数:" + acc.value + ", action执行之前")
        println("pairs中总共有多少条记录:" + pairs.count())
        println("you出现的次数:" + acc.value + ", action执行之后")
        acc.reset()//重置累加器的值
        pairs.countByKey()
        /*
            解决这个重复调用的问题:
            1、要么在第一次出现action之后调用
            2、再一次执行action之前,重置累加器的值
         */
        println("you出现的次数:" + acc.value + ", action执行之后")


//        Thread.sleep(1000000)
        sc.stop()
    }
}

 

 

 

 

 

 

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值