Accumulator-累加器的簡單使用及注意事項

累加器用於在executors中做變量更改。
官方文檔: 官方文檔地址

基於spark 2.3.3版本編寫的示例demo :

package pers.nebo.sparkcore
import org.apache.spark.rdd.RDD
import org.apache.spark.sql.SparkSession
import org.apache.spark.util.LongAccumulator

/**
  * @ author fnb
  * @ email [email protected]
  * @ date  2019/12/1
  * @ des : 累加器的使用
  *
  *(1) 如果沒觸發到action , 由於 lazy 不會觸發,累加器的值也不會發生變化。
  *(2)一個action 操作,會觸發一次累加器,所以如果多個action操作的話,中間使用cache() ,
  * 這樣下一個aciton會使用cache的內容,則不會多計算累加器
  */
object AccumulatorTest {

  def main(args: Array[String]): Unit = {
  
    val spark=SparkSession.builder().appName("test").master("local").getOrCreate()
    val sc=spark.sparkContext
    val accumulator:LongAccumulator =sc.longAccumulator
    val rdd1:RDD[String] =sc.textFile("/DATA/topN.txt")
    var i=0

    val rdd2=rdd1.map(line=>{
//      i+=1
       accumulator.add(1)
      // 1.6 不能直接使用accumulator.value 獲取值,只能打印對象, 2.x 可以
      println(s"Exector accumulator= ${accumulator}")
      line
    })
    rdd2.collect()
    println(s"i= ${accumulator.value}")



//下面爲需要注意的使用點,多個action 會導致累加器,重複計算,需要處理一下。

    val accumulator2:LongAccumulator =sc.longAccumulator
    val rdd3:RDD[String] =sc.textFile("/DATA/topN.txt",2)
    println("rdd3  partition length==="+rdd3.getNumPartitions)
    val rdd4=rdd3.map(line=>{
      //      i+=1
      accumulator2.add(1)
      // 1.6 不能直接使用accumulator.value 獲取值,只能打印對象, 2.x 可以
      println(s"Exector accumulator= ${accumulator}")
      line
    })
    //使用cache 這樣下一次就不會再觸發累加器了。註釋掉下面這行累加器則會翻倍。
    // rdd4.cache()
    // 這裏的sortby 沒有任何意思只是爲了使用sort 函數
    val rdd5= rdd4.sortBy(line=>{})
    // sort by key 當你的分區大於1的時候,它會有一個抽樣 ,觸發rdd的action
    rdd5.collect()
    println(s"i= ${accumulator2.value}")
  }
}

源碼: github源碼

問題:

rdd轉化的時候((val rdd5= rdd4.sortBy(line=>{})))報錯

java.lang.NoSuchMethodError:net.jpountz.lz4.LZ4BlockInputStream

參考:解決博客

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章