Spark Streaming(一)—— Spark Streaming介紹

1. 什麼是Spark Streaming

Spark Streaming makes it easy to build scalable fault-tolerant streaming applications.
易於構建靈活的、高容錯的流式系統。

流式計算框架

Spark Streaming是核心Spark API的擴展,可實現可擴展、高吞吐量、可容錯的實時數據流處理。數據可以從諸如Kafka,Flume,Kinesis或TCP套接字等衆多來源獲取,並且可以使用由高級函數(如map,reduce,join和window)開發的複雜算法進行流數據處理。最後,處理後的數據可以被推送到文件系統,數據庫和實時儀表板。而且還可以在數據流上應用Spark提供的機器學習和圖處理算法。

在這裏插入圖片描述

2. Spark Streaming特點

  • 易用:已經集成在Spark中
  • 容錯性:底層也是RDD,RDD本身就具備了容錯機制。
  • 支持多種語言:Java Scala Python

3. 常用的實時計算引擎

  1. Apache Storm:真正的流式計算

  2. Spark Streaming:嚴格上來說,Spark Streaming不是真正的流式計算。

    把連續的流式數據,當成不連續的RDD來處理。
    本質上:是一個離線計算。當採樣時間特別短時,可以看成是流式計算。

  3. Flink:真正的流式計算。跟Spark Streaming 相反。

    把離散的數據,當成流式數據來處理。
    目前還不穩定。從1.8升級到1.9就有很多改變。而且對語言這塊,支持比較好的也只是Java和Scala。而且對於機器學習建模這塊,雖然有這個東西,但是跟Spark相比,還是有很大差距。所以目前用到最多的還是Spark。Flink是一個未來的東西。

4. Spark Streaming內部結構

內部工作原理如下。Spark Streaming接收實時輸入數據流,並將數據切分成批,然後由Spark引擎對其進行處理,最後生成“批”形式的結果流。

在這裏插入圖片描述

Spark Streaming將連續的數據流抽象爲discretizedstream或DStream。在內部,DStream 由一個RDD序列表示。

5. StreamingContext對象創建方式

方式一:通過SparkConf創建

//local[2]代表開啓兩個線程
val conf = new SparkConf().setAppName("MyNetwordWordCount").setMaster("local[2]")
     
//接收兩個參數,第一個conf,第二個是採樣時間間隔
val ssc = new StreamingContext(conf,Seconds(3))

程序中的幾點說明:

  • appName參數是應用程序在集羣UI上顯示的名稱。
  • master是Spark,Mesos或YARN集羣的URL,或者一個特殊的“local [*]”字符串來讓程序以本地模式運行。
  • 當在集羣上運行程序時,不需要在程序中硬編碼master參數,而是使用spark-submit提交應用程序並將master的URL以腳本參數的形式傳入。但是,對於本地測試和單元測試,可以通過“local[*]”來運行Spark Streaming程序(請確保本地系統中的CPU核數夠用)。
  • StreamingContext會內在的創建一個SparkContext的實例(所有Spark功能的起始點),你可以通過ssc.sparkContext訪問到這個實例。
  • 批處理的時間窗口長度必須根據應用程序的延遲要求和可用的集羣資源進行設置。

請務必記住以下幾點:

  • 一旦一個StreamingContext開始運作,就不能設置或添加新的流計算。
  • 一旦一個上下文被停止,它將無法重新啓動。
  • 同一時刻,一個JVM中只能有一個StreamingContext處於活動狀態。
  • StreamingContext上的stop()方法也會停止SparkContext。 要僅停止StreamingContext(保持SparkContext活躍),請將stop() 方法的可選參數stopSparkContext設置爲false。
  • 只要前一個StreamingContext在下一個StreamingContext被創建之前停止(不停止SparkContext),SparkContext就可以被重用來創建多個StreamingContext。

方式二:從現有的SparkContext實例中創建

在這裏插入圖片描述

6. 離散流DStream

6.1 什麼是DStream

DStream(DiscretizedStream),是Spark Streaming對流式數據的基本抽象。它表示連續的數據流,這些連續的數據流可以是從數據源接收的輸入數據流,也可以是通過對輸入數據流執行轉換操作而生成的經處理的數據流。在內部,DStream由一系列連續的RDD表示。

簡單的說,就是把連續的數據變成不連續的RDD。DStream是RDD的集合,包含不連續的RDD。DStream的每一個RDD都包含一定時間間隔內的數據。表現形式依然是RDD。操作DStream和操作RDD是一樣的。

6.2 DStream中的算子

在這裏插入圖片描述

  • transform(func)

    val wordCount = words.map((_,1)).reduceByKey(_+_)

    等價於 ==>
    val wordCount = words.transform(x => x.map((_,1))).reduceByKey(_+_)

  • updateStateByKey(func)

    默認情況下,Spark Streaming 不記錄之前的狀態,每次發一條數據,都是從0開始計算。用這個算子可以實現更新DStream的狀態。

    import org.apache.log4j.Logger
    import org.apache.log4j.Level
    import org.apache.spark.SparkConf
    import org.apache.spark.streaming.StreamingContext
    import org.apache.spark.streaming.Seconds
    import org.apache.spark.storage.StorageLevel
     
    object MyTotalNetworkWordCount {
       
      def main(args: Array[String]): Unit = {
         
        System.setProperty("hadoop.home.dir", "G:\\bin\\hadoop-2.5.2")
        Logger.getLogger("org.apache.spark").setLevel(Level.ERROR)
        Logger.getLogger("org.eclipse.jetty.server").setLevel(Level.OFF)
         
        val conf = new SparkConf().setMaster("local[2]").setAppName("MyTotalNetworkWordCount")
         
        val ssc = new StreamingContext(conf,Seconds(3))
         
        //設置檢查點目錄,保存之前的狀態信息
        ssc.checkpoint("hdfs://topnpl200:8020/tmp_files/chkp0826")
         
        val lines = ssc.socketTextStream("192.168.15.131", 1234, StorageLevel.MEMORY_ONLY)
         
        val words = lines.flatMap(_.split(" "))
         
        val wordPair = words.map((_,1))
         
        /**
         * 兩個參數:
         * 第一個參數:當前的值是多少
         * 第二個參數:之前的結果是多少
         */
        val addFunc = (curreValues:Seq[Int],previousValues:Option[Int]) => {
          // 進行累加運算
          
          // 1、把當前值的序列進行累加
          val currentTotal = curreValues.sum
           
          //2、在之前的值上再累加
          Some( currentTotal + previousValues.getOrElse(0) )
        }
         
        //進行累加運算
        val total = wordPair.updateStateByKey(addFunc)
         
        total.print()
         
        ssc.start()
        ssc.awaitTermination()
         
      }
    }
    

7. 窗口

處理落在窗口中的數據。也是DStream,也是RDD。

注意:

窗口參數有要求,不能隨便設置。窗口大小和移動大小,都必須是DStream的批間隔的整數倍。

import org.apache.log4j.Logger
import org.apache.log4j.Level
import org.apache.spark.SparkConf
import org.apache.spark.streaming.StreamingContext
import org.apache.spark.streaming.Seconds
import org.apache.spark.storage.StorageLevel
 
/**
 * 需求:每10秒,對過去30秒的數據進行累加
 *
 * 窗口長度:30秒
 *
 * 滑動距離:10秒
 *
 */
object MyNetWorkWordCountByWindow {
 
  def main(args: Array[String]): Unit = {
    System.setProperty("hadoop.home.dir", "G:\\bin\\hadoop-2.5.2")
    Logger.getLogger("org.apache.spark").setLevel(Level.ERROR)
    Logger.getLogger("org.eclipse.jetty.server").setLevel(Level.OFF)
     
    val conf = new SparkConf().setAppName("MyNetWorkWordCountByWindow").setMaster("local[2]")
     
    // 這裏設成3s會報錯。改成1s。
    val ssc = new StreamingContext(conf,Seconds(1))
     
    val lines = ssc.socketTextStream("192.168.15.131", 1234, StorageLevel.MEMORY_ONLY)
     
    val words = lines.flatMap(_.split(" ")).map((_,1))
     
    /**
     * reduce By Key And Window
     * 三個參數
     * 1、要進行什麼操作
     * 2、窗口的大小
     * 3、窗口滑動的距離
     */
     
    val result = words.reduceByKeyAndWindow((x:Int,y:Int)=>(x+y),Seconds(30),Seconds(10))
     
    result.print()
     
    ssc.start()
    ssc.awaitTermination()
       
  }
 
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章