广播变量案列练习

package cn._51doit.day06

import org.apache.spark.rdd.RDD
import org.json4s.scalap.scalasig.ScalaSigEntryParsers.index
import utils.{IpUtils, SparkUtils}

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

    val sc = SparkUtils.createContext(args(0).toBoolean)

     // 使用 spark 读取 IP 规则数据
    val ipLines: RDD[String] = sc.textFile(args(1))
    val ipRulesRDD: RDD[(Long, Long, String, String)] = ipLines.map(e => {
      val fields = e.split("[|]") // 以 | 切割 , 在正则表达式中是特殊符号,所以要拿 []
      val startNum = fields(2).toLong //   16777472 切割出 第二个来
      val endNum = fields(3).toLong //   16778239 切割出 第三个来
      val province = fields(6) //   福建   省份
      val city = fields(7) //  福州    城市
      (startNum, endNum, province, city)
    })
    //  将整理后的ip 规则收集到 Drive 端  前提是内存够用,否则它只会传部分数据
    val ipRulesInDrive: Array[(Long, Long, String, String)] = ipRulesRDD.collect()
    //  将Driver 的 IP 规则数据广播到 Executor 中,该方法是一个阻塞的方法
    //  意味着没广播完 Driver 端不会往下走
    //  broadcastRef 这个引用 可以知道它把数据广播到哪一个节点上了,然后再每一个数据上它的内存地址
    val broadcastRef = sc.broadcast(ipRulesInDrive)
    //  读取访问日志的数据
    val accessLog: RDD[String] = sc.textFile(args(2))
    val provinceAndOne = accessLog.map(e => {
      val fields = e.split("[|]")
      val ip = fields(1)
      // 将IP地址转成十进制
      val ipNum = IpUtils.ip2Long(ip)

      // 通过Driver 返回的广播变量的引用,获取事先已经广播到当前 Executor 中的数据
      val ipRulesInExecutor: Array[(Long, Long, String, String)] = broadcastRef.value
      // 进行二分查找
      val index = IpUtils.binarySearch(ipRulesInExecutor, ipNum)
      var province = " 未知"
      if (index >= 0) {
       province = ipRulesInExecutor(index)._3
      }
      (province, 1)
    })

    val reduced = provinceAndOne.reduceByKey(_ + _)
    val res = reduced.collect()
    println(res.toBuffer)
    sc.stop()

  }
}

在这里插入图片描述

广播变量通常是为了实现 mapSideJoin 减少网络传输 ,可以将小的数据广播到属于 该 application 的 Executor 中 ,要广播的数据不宜太大,要根据 服务器的内存和分配的 executor-memory 决定

广播变量是 readonly,一但广播出去就不能改变了

但是在Driver 可以调用 unpersist 将广播变量释放,如果以后在 Executor 用到该变量,需要重新广播

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值