Spark 누산기의 역할 및 사용

누산기 기능

  • 누산기 : 분산 쓰기 전용 변수 (실행기 측의 작업은 서로의 누산기 값에 액세스 할 수 없음).
  • 누산기는 정보를 집계합니다. Spark에 함수를 전달할 때 일반적으로 Driver 측에 정의 된 변수를 사용할 수 있지만 Executor 측에서이 변수를 사용하면 각 태스크가이 변수의 사본을 사용합니다. 변수의 값이 변경되면 드라이버 측의 변수 값은 변경되지 않습니다.
  • 누산기를 통해 슬라이스 처리를 구현하고 동시에 변수 값을 업데이트 할 수 있습니다.

기본 누산기 사용

수요

        셔플없이 단어 빈도 통계 실현

bject Spark06_Accumulator {
    
    
  def main(args: Array[String]): Unit = {
    
    
    val conf: SparkConf = new SparkConf().setAppName(this.getClass.getName).setMaster("local[*]")
    val sc = new SparkContext(conf)
    val rdd: RDD[(String, Int)] = sc.makeRDD(List(("a", 1), ("b", 2), ("a", 3), ("b", 4)))
    // 声明累加器
    val sumAcc: LongAccumulator = sc.longAccumulator("sumAcc")
    rdd.foreach {
    
    
      case (word, count) => {
    
    
        // 使用累加器
        sumAcc.add(count)
      }
    }
    // 累加器的toString方法
    //println(sumAcc)
    //取出累加器中的值
    println(sumAcc.value)
    sc.stop()
  }
}

맞춤형 누산기

수요

        셔플을 사용하지 않고 H로 시작하는 단어의 수를 센다.

object Spark07_MyAccumulator {
    
    
  def main(args: Array[String]): Unit = {
    
    
    val conf: SparkConf = new SparkConf().setAppName(this.getClass.getName).setMaster("local[*]")
    val sc = new SparkContext(conf)
    val rdd: RDD[String] = sc.makeRDD(List("Hello", "HaHa", "spark", "scala", "Hi", "Hello", "Hi"))
    // 创建累加器
    val myAcc = new MyAccumulator
    //注册累加器
    sc.register(myAcc, "MyAcc")
    rdd.foreach{
    
    
      datas => {
    
    
        // 使用累加器
        myAcc.add(datas)
      }
    }
    // 获取累加器的结果
    println(myAcc.value)

    sc.stop()
  }
}

// 自定义累加器
// 泛型分别为输入类型和输出类型
class MyAccumulator extends AccumulatorV2[String, mutable.Map[String, Int]] {
    
    
  // 定义输出数据变量
  var map: mutable.Map[String, Int] = mutable.Map[String, Int]()

  // 累加器是否为初始状态
  override def isZero: Boolean = map.isEmpty

  // 复制累加器
  override def copy(): AccumulatorV2[String, mutable.Map[String, Int]] = {
    
    
    val MyAcc = new MyAccumulator
    // 将此累加器中的数据赋值给新创建的累加器
    MyAcc.map = this.map
    MyAcc
  }

  // 重置累加器
  override def reset(): Unit = {
    
    
    map.clear()
  }

  // 累加器添加元素
  override def add(v: String): Unit = {
    
    
    if (v.startsWith("H")) {
    
    
      // 判断map集合中是否已经存在此元素
      map(v) = map.getOrElse(v, 0) + 1
    }
  }

  // 合并累加器中的元素
  override def merge(other: AccumulatorV2[String, mutable.Map[String, Int]]): Unit = {
    
    
    val map1: mutable.Map[String, Int] = this.map
    val map2: mutable.Map[String, Int] = other.value
    // 合并两个map
    map = map1.foldLeft(map2) {
    
    
      (m, kv) => {
    
    
        m(kv._1) = m.getOrElse(kv._1, 0) + kv._2
        m
      }
    }
  }

  // 获取累加器中的值
  override def value: mutable.Map[String, Int] = {
    
    
    map
  }
}

추천

출처blog.csdn.net/FlatTiger/article/details/115133641