Spark学习——累加器(Accumulator)

累加器主要用于多个节点对同一变量进行操作,可以在executor端使用driver端定义的变量;但是executor并不能读取累加器的值。

    累加器的类型 1.Accumulator[Int] 2.Accumulator[Double] 3.Accumulator[Long]等 自定义累加器 1.spark1 只需要继承AccumulatorParam,并重写 addInPlace()//累加操作 zero()//默认值 下面是自定义String类型的累加器(scala版本),代码如下:
object StringAccumulator extends  AccumulatorParam[String]{
          
   
//简单拼接
  override def addInPlace(r1: String, r2: String): String = {
          
    r1+" "+r2 }

  override def zero(initialValue: String): String = {
          
   ""}
}

2.spark2 相比spark1,spark2版本的累加器稍显复杂,需要继承 AccumulatorV2并重写 add()//累加操作 isZero()//判空 copy()//复制 reset()//清空 merge()//合并 value()//获取value

下面是自定义Json类型累加器(scala版本),代码如下:

class JsonAccumulator extends AccumulatorV2[String,JSONObject]{
          
   

  private val jsonAccumulator = new JSONObject()

  override def add(v:String): Unit = {
          
   
    val keyvalue = v.split(",")
    val key = keyvalue(0)
    val value = keyvalue(1)
    jsonAccumulator.put(key,value)
  }

  override def isZero: Boolean = {
          
   
    jsonAccumulator.isEmpty
  }

  override def copy(): AccumulatorV2[String, JSONObject] = {
          
   
    val newjsonAccumulator = new JsonAccumulator()
    import collection.JavaConversions._
    for(key<-jsonAccumulator.keySet()){
          
   
      newjsonAccumulator.add(key+","+jsonAccumulator.getString(key))
    }

    newjsonAccumulator
  }

  override def reset(): Unit = {
          
   jsonAccumulator.clear()}

  override def merge(other: AccumulatorV2[String, JSONObject]): Unit = {
          
   
    val keyset =  other.value.keySet()
    import collection.JavaConversions._
    for(key<-keyset){
          
   
      jsonAccumulator.put(key,other.value.getString(key))
    }
  }

  override def value: JSONObject = {
          
   jsonAccumulator}

}
    使用累加器

(1) 使用内置累加器 (2)使用自定义累加器 spark1版本:

//上面自定义的string类型累加器
sparkContext.accumulator("")(StringAccumulator)

spark2版本:

val jsonAccumulator = new JsonAccumulator
    sparkContext.register(jsonAccumulator)

完整代码(json为例)

object test_wangty {
          
   

  def main(args: Array[String]): Unit = {
          
   
    val sparkConf = new SparkConf()
    val sparkContext = new SparkContext(sparkConf)
    val hiveContext = new HiveContext(sparkContext)
    val sqlContext = new SQLContext(sparkContext)

    val sql =
      s"""
         |select
         |group_id,
         |cast(amount as string) amount
         |from
         |test.test_wangty
         |where
         |dt = 2020-05-01
         |limit 10
      """.stripMargin

    val rs = sqlContext.sql(sql).rdd
    val jsonAccumulator = new JsonAccumulator
    sparkContext.register(jsonAccumulator)
    rs.repartition(10).foreach(x=>
      jsonAccumulator.add(x.getString(1)+","+x.getString(2))
    )

    println(jsonAccumulator.value.toJSONString)

    sparkContext.stop()



  }

}

结果如下:

经验分享 程序员 微信小程序 职场和发展