簡體   English   中英

火花蓄能器

[英]Spark Accumulator

我是 Spark 中的累加器的新手。 我創建了一個累加器,它將數據框中所有列的總和和計數信息收集到一個 Map 中。 哪個沒有按預期運行,所以我有一些疑問。

當我在本地模式下運行這個類(粘貼在下面)時,我可以看到累加器得到更新,但最終值仍然是空的。出於調試目的,我在 add() 中添加了一個打印語句。

Q1) 為什么在添加累加器時最終的累加器沒有更新?

作為參考,我研究了 CollectionsAccumulator,他們在其中使用了 Java Collections 中的 SynchronizedList。

Q2) 累加器更新是否需要同步/並發集合?

Q3) 哪個系列最適合這樣的目的?

我附上了我的執行流程和 spark ui 快照以供分析。

謝謝。

執行:

輸入數據幀 -

+-------+-------+
|Column1|Column2|
+-------+-------+
|1      |2      |
|3      |4      |
+-------+-------+

輸出 -

添加 - Map(Column1 -> Map(sum -> 1, count -> 1), Column2 -> Map(sum -> 2, count -> 1))

添加 - Map(Column1 -> Map(sum -> 4, count -> 2), Column2 -> Map(sum -> 6, count -> 2))

TestRowAccumulator(id: 1, name: Some(Test Accumulator for Sum&Count), value: Map())

SPARK 用戶界面快照 -

SPARK 用戶界面 -

班級 :

class TestRowAccumulator extends AccumulatorV2[Row,Map[String,Map[String,Int]]]{

  private var colMetrics: Map[String, Map[String, Int]] = Map[String , Map[String , Int]]()


  override def isZero: Boolean = this.colMetrics.isEmpty

  override def copy(): AccumulatorV2[Row, Map[String,Map[String,Int]]] = {
    val racc = new TestRowAccumulator
    racc.colMetrics = colMetrics
    racc
  }

  override def reset(): Unit = {
    colMetrics = Map[String,Map[String,Int]]()
  }

  override def add(v: Row): Unit = {

    v.schema.foreach(field => {
      val name: String = field.name
      val value: Int = v.getAs[Int](name)
      if(!colMetrics.contains(name))
        {
          colMetrics = colMetrics ++ Map(name -> Map("sum" -> value , "count" -> 1 ))
        }else
        {
          val metric = colMetrics(name)
          val sum = metric("sum") + value
          val count = metric("count") + 1

          colMetrics = colMetrics ++ Map(name -> Map("sum" -> sum , "count" -> count))
        }
    })
  }

  override def merge(other: AccumulatorV2[Row, Map[String,Map[String,Int]]]): Unit = {
    other match {
      case t:TestRowAccumulator => {
        colMetrics.map(col => {
          val map2: Map[String, Int] = t.colMetrics.getOrElse(col._1 , Map())
          val map1: Map[String, Int] = col._2
          map1 ++ map2.map{ case (k,v) => k -> (v + map1.getOrElse(k,0)) }
        } )
      }
      case _ => throw new UnsupportedOperationException(s"Cannot merge ${this.getClass.getName} with ${other.getClass.getName}")
    }
  }

  override def value: Map[String, Map[String, Int]] = {
    colMetrics
  }
}

經過一些調試,我發現正在調用合並函數。 它有錯誤的代碼,所以可累積的值是 Map()

累加器的執行流程(本地模式):添加添加合並

一旦我更正了合並功能,累加器就會按預期工作

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM