spark 累加器、广播变量、Executor 的结构

spark 累加器

package com.shujia.spark

import java.lang

import org.apache.spark.rdd.RDD
import org.apache.spark.util.LongAccumulator
import org.apache.spark.{SparkConf, SparkContext}

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

    val sc = new SparkContext(conf)

    val studentsRDD: RDD[String] = sc.textFile("data/students.txt")

    var count = 0

    studentsRDD.foreach(
      student => {
        //在算子内修改算子外的一个变量不会生效
        count += 1
        println(count)  //里面的count是一个变量副本,会生效
        println(student) //这里加上一个输出,我们发现代码是运行的,所以下面的count:0并不是代码没有运行
      }
    )

    //为什么呢?
    println(s"count:$count") //count:0

    /**
      * 累加器
      *
      * 累加器有局限性:仅能做累加、累减
      * 因为这是一个并行计算的环境,多个task对同一个数据做修改,易发生线程安全的问题
      */
    //1、在Driver端定义一个累加器(这里是Long类型的)
    val accCount: LongAccumulator = sc.longAccumulator

    studentsRDD.foreach(student => {
      //2、在Executor端对累加器进行累加计算
      accCount.add(1)
    })

    //3、在Driver端读取累加结果
    val studentCount: Long = accCount.value

    println(s"studentCount:$studentCount")

  }
}

广播变量

package com.shujia.spark

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

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

    val sc = new SparkContext(conf)

    val studentsRDD: RDD[String] = sc.textFile("data/students.txt")

    /**
      * 取出集合中的所有学生的信息
      *
      */
      
    val ids = List("1500100006", "1500100011", "1500100016", "1500100041")

    /*   
    val filterRDD: RDD[String] = studentsRDD.filter(student => {
        val id: String = student.split(",")(0)

        ids.contains(id)
    })

        filterRDD.foreach(println)
    */

    /**
      * 使用广播变量
      *
      */

    //1、将Driver端的一个变量广播出去 broadcast(ids) 
    val broIds: Broadcast[List[String]] = sc.broadcast(ids)

    val filterRDD: RDD[String] = studentsRDD.filter(student => {
      val id: String = student.split(",")(0)

      //2、在task中获取广播变量 broIds.value
      val value: List[String] = broIds.value

      value.contains(id)
    })

    filterRDD.foreach(println)
  }
}

Executor 的结构

posted @ 2022-03-11 10:07  赤兔胭脂小吕布  阅读(42)  评论(0编辑  收藏  举报