Sparkstreaming常用算子詳解

一.基本算子

在這裏插入圖片描述
中文翻譯:
在這裏插入圖片描述

二.updateStateByKey

updateStateByKey操作可以保持任意狀態,同時不斷用新信息更新它。要使用此功能,必須執行兩個步驟。

  1. 定義狀態-狀態可以是任意數據類型。
  2. 定義狀態更新功能-使用功能指定如何使用輸入流中的先前狀態和新值來更新狀態。

在每個批次中,Spark都會對所有現有密鑰應用狀態更新功能,而不管它們是否在批次中具有新數據。如果更新函數返回,None將刪除鍵值對。

讓我們用一個例子來說明。假設要保持在文本數據流中看到的每個單詞的連續計數。此處,運行計數是狀態,它是整數。將更新函數定義爲:

def updateFunction(newValues: Seq[Int], runningCount: Option[Int]): Option[Int] = {
    val newCount = ...  // add the new values with the previous running count to get the new count
    Some(newCount)
}

這適用於包含單詞的DStream【wordcount會把單詞映射爲(word, 1)對的DStream】。
調用如下:

val runningCounts = pairs.updateStateByKey[Int](updateFunction _)

將爲每個單詞調用更新函數,每個單詞newValues的序列爲1(來自各(word, 1)對),並且runningCount具有先前的計數。

請注意,使用updateStateByKey需要配置檢查點目錄。

ssc.checkpoint("D:\\checkpoint")

完整代碼:

package spark2.streaming

import org.apache.log4j.{Level, Logger}
import org.apache.spark.SparkConf
import org.apache.spark.streaming.{Seconds, StreamingContext}

/**
  * Created by Administrator on 2020/5/7.
  */
object UpdateStateByKey {
  /**
    * 累加
    * @param newValues  當前週期新數據的值
    * @param runningCount  歷史累計值
    * @return
    */
  def updateFunction(newValues : Seq[Int], runningCount : Option[Int]) : Option[Int] = {
    val preCount = runningCount.getOrElse(0)
    val newCount = newValues.sum
    Some(newCount + preCount) // 累加
  }

  Logger.getLogger("org").setLevel(Level.WARN) // 設置日誌級別
  def main(args: Array[String]) {
    val conf = new SparkConf().setMaster("local[2]").setAppName(s"${this.getClass.getSimpleName}")
    val ssc = new StreamingContext(conf,Seconds(5))
    // 設置檢測點
    ssc.checkpoint("E:\\checkpoint")
    val lines = ssc.socketTextStream("master",9999) // 與nc端口對應
    val words = lines.flatMap(_.split(" "))
    var pairs = words.map(word=>(word,1)).reduceByKey(_+_)
    // 累加
    pairs = pairs.updateStateByKey[Int](updateFunction _) // 必須設置檢查點
    pairs.foreachRDD(row => row.foreach(println))
    ssc.start()
    ssc.awaitTermination()
    ssc.stop()
  }
}

執行結果:
在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述

三.Transform

transform操作【及其類似的變體transformWith】允許將任意RDD-to-RDD功能應用於DStream。它可用於應用DStream API中未公開的任何RDD操作。例如,將數據流中的每個rdd與另一個數據集連接在一起的功能未直接在DStream API中公開。但是,可以輕鬆地使用transform來執行此操作。這實現了非常強大的可能性。例如,可以通過將輸入數據流與預先計算的垃圾郵件信息【也可能由Spark生成】結合在一起,然後基於該信息進行過濾來進行實時數據清理。

val spamInfoRDD = ssc.sparkContext.newAPIHadoopRDD(...) // RDD containing spam information

val cleanedDStream = wordCounts.transform { rdd =>
  rdd.join(spamInfoRDD).filter(...) // join data stream with spam information to do data cleaning
  ...
}

請注意,在每個批處理間隔中都會調用提供的函數。這使得可以執行隨時間變化的RDD操作,即可以在批之間更改RDD操作,分區數,廣播變量等。

完整代碼:

package spark2.streaming

import org.apache.log4j.{Level, Logger}
import org.apache.spark.sql.SparkSession
import org.apache.spark.streaming.{Seconds, StreamingContext}

/**
  * Created by Administrator on 2020/6/23.
  */
object StreamingTransform {
  Logger.getLogger("org").setLevel(Level.WARN) // 設置日誌級別
  def main(args: Array[String]) {
    val spark = SparkSession.builder()
      .appName(s"${this.getClass.getSimpleName}")
      .master("local[2]")
      .getOrCreate()
    val sc = spark.sparkContext

    /**
      * 生成數據集,黑名單,寫在ssc之前,避免多次執行
      */
    val array = Array[String]("spark,1", "flink,0", "storm,0")
    val filters = sc.parallelize(array).map(row => (row.split(",")(0), row.split(",")(1).toInt))

    filters.count()
    filters.foreach(println)

    val ssc = new StreamingContext(sc,Seconds(5))

    val lines = ssc.socketTextStream("master",9999) // 與nc端口對應
    val words = lines.flatMap(_.split(" "))
    val pairs = words.map(word=>(word, 1)).reduceByKey(_+_)

    /**
      * 關聯
      */
    pairs.foreachRDD(rdd =>{
      val mid = rdd.leftOuterJoin(filters).map(row =>{
          val filter = row._2._2 match { // 模式匹配
            case Some(a) => a
            case None => 0
          }
          (row._1, row._2._1, filter)
        })
        .filter(_._3 == 1) // filter == 1
        .map(row => (row._1, row._2))

      mid.foreach(println)
    })

    ssc.start()
    ssc.awaitTermination()
    ssc.stop()
  }
}

執行結果:

Using Spark's default log4j profile: org/apache/spark/log4j-defaults.properties
20/06/23 20:20:43 WARN NativeCodeLoader: Unable to load native-hadoop library for your platform... using builtin-java classes where applicable
(flink,0)
(spark,1)
(storm,0)
20/06/23 20:21:01 WARN RandomBlockReplicationPolicy: Expecting 1 replicas with only 0 peer/s.
20/06/23 20:21:01 WARN BlockManager: Block input-0-1592914861200 replicated to only 0 peer(s) instead of 1 peers
(spark,1)
20/06/23 20:21:33 WARN RandomBlockReplicationPolicy: Expecting 1 replicas with only 0 peer/s.
20/06/23 20:21:33 WARN BlockManager: Block input-0-1592914893200 replicated to only 0 peer(s) instead of 1 peers
(spark,2)

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