spark--累加器-★★★

累加器

  • 现象比较难理解,但是代码很简单
package cn.hanjiaxiaozhi.core

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

/**
 * Author hanjiaxiaozhi
 * Date 2020/7/23 10:17
 * Desc 演示Spark累加器
 */
object AccumulatorTest {
  def main(args: Array[String]): Unit = {
    //0.创建sc-Spark执行环境
    val conf: SparkConf = new SparkConf().setAppName("wc").setMaster("local[*]")//虽然是local,但是运行机制和集群一样,是用本地线程模拟集群
    val sc: SparkContext = new SparkContext(conf)
    sc.setLogLevel("WARN")

    //1.使用Scala集合完成累计
    var counter1:Int = 0
    val data: List[Int] = List(1,2,3,4,5) //和为15
    data.foreach(i=>{
      counter1 += i
    })
    println(counter1)//15,肯定没有问题
    println("===============")

    //2.使用Spark完成累计-不使用累加器
    var counter2 :Int = 0
    val dataRDD: RDD[Int] = sc.parallelize(List(1,2,3,4,5))//和为15
    dataRDD.foreach(i=>{
      counter2+=i
    })
    println(counter2)//0,为什么是0?
    //注意:如果使用RDD的foreach然后将i累计到counter2上去counter2的结果是0
    //因为dataRDD.foreach中的函数是作用在各个元素上,而这些元素都在各个Worker机器上,所以累加的结果是给到了各个机器的counter2上面了
    //和Driver端的counter2没关系,所以Driver端的Counter2结果还是0!
    //现在产生这个现象的原因已经知道了,那么得解决,也就是要使用Spark的累加器完成累加
    println("===============")

    //3.使用Spark完成累计-使用累加器
    val counter3: LongAccumulator = sc.longAccumulator //使用sc创建一个累加器,而sc可以和集群通信,那么后续各个Worker可以将结果累计到该累加器上
    //    val counter4: LongAccumulator = sc.longAccumulator() //错误
    dataRDD.foreach(i=>{
          counter3.add(i)
        })
    println(counter3.value)//15
    //注意:这里使用了累加器,所以i可以往累加器上加
  }
}

你可能感兴趣的:(Spark,spark)