Spark Streaming 的原理以及應用場景介紹

五柳-先生發表於2016-01-29
  1. 什麼是Spark Streaming
    Spark Streaming類似於Apache Storm,用於流式資料的處理。根據其官方文件介紹,Spark Streaming有高吞吐量和容錯能力強這兩個特點。Spark Streaming支援的資料輸入源很多,例如:Kafka、Flume、Twitter、ZeroMQ和簡單的TCP套接字等等。資料輸入後可以用 Spark的高度抽象原語如:map、reduce、join、window等進行運算。而結果也能儲存在很多地方,如HDFS,資料庫等。另外 Spark Streaming也能和MLlib(機器學習)以及Graphx完美融合。大概架構如下:

  2. Spark Streaming 執行原理
    Spark Streaming的基本原理是將輸入資料流以時間片(秒級)為單位進行拆分,然後以類似批處理的方式處理每個時間片資料,基本原理圖如下:

    首先,Spark Streaming把實時輸入資料流以時間片Δt (如1秒)為單位切分成塊。Spark Streaming會把每塊資料作為一個RDD,並使用RDD操作處理每一小塊資料。每個塊都會生成一個Spark Job處理,最終結果也返回多塊。

  3. SparkStreaming 支援的業務場景
    目前而言SparkStreaming 主要支援以下三種業務場景
    1. 無狀態操作:只關注當前的DStream中的實時資料,例如 只對當前DStream中的資料做正確性校驗
    2. 有狀態操作:對有狀態的DStream進行操作時,需要依賴之前的資料 例如 統計網站各個模組總的訪問量
    3. 視窗操作:對指定時間段範圍內的DStream資料進行操作,例如 需要統計一天之內網站各個模組的訪問數量
  4. SparkStreaming 支援的操作
    Discretized Stream是Spark Streaming的基礎抽象,代表持續性的資料流和經過各種Spark原語操作後的結果資料流。在內部實現上,DStream由連續的序列化RDD來表示。支援的操作主要包含以下幾種
    1. Action
      1. 當某個Output Operations原語被呼叫時,stream才會開始真正的計算過程。現階段支援的Output方式有以下幾種:
      •     print() 
      •     foreachRDD(func)
      •     saveAsObjectFiles(prefix, [suffix])
      •     saveAsTextFiles(prefix, [suffix])
      •     saveAsHadoopFiles(prefix, [suffix])
    2. 常規RDD 的Transformation操作
      對常規RDD使用的transformation操作,在DStream上都適用 
    3. 有狀態的Transformation
      • UpdateStateByKey:使用該方法主要是使用目前的DStream資料來更新歷史資料
    4. 視窗的 Transformation
      Window Operations有點類似於Storm中的State,可以設定視窗的大小和滑動視窗的間隔來動態的獲取當前Steaming的允許狀態。如下圖所示:

      主要支援的操作有:
      • window(windowLength, slideInterval)
      • countByWindow(windowLength, slideInterval)
      • reduceByWindow(func, windowLength, slideInterval)
      • reduceByKeyAndWindow(func, windowLength, slideInterval, [numTasks])
      • reduceByKeyAndWindow(func, invFunc, windowLength, slideInterval, [numTasks])
      • countByValueAndWindow(windowLength, slideInterval, [numTasks])
  5. 持久化以及容錯
    1. 持久化

      與RDD一樣,DStream同樣也能通過persist()方法將資料流存放在記憶體中,這樣做的好處是遇到需要多次迭代計算的程式時,速度優勢十分的明顯。
      而對於上文中提到的Window以及Stateful的操作,其預設的持久化策略就是儲存在記憶體中MEMORY_ONLY_SER)。
      當資料來源來自於網路時(例如通過Kafka、Flume、sockets等等),由於網路資料的不可在再現性,預設的持久化策略是MEMORY_AND_DISK_SER_2(將資料儲存在兩臺機器上),這也是為了容錯性而設計的。

      關於持久化,還有一點需要注意的就是,由於資料流的持續處理,在記憶體的消耗上可能比較大,為了緩解記憶體的壓力引入了checkpoint的概念,checkpoint有以下幾點需要注意:

      – 對於 window 和 stateful 操作必須 checkpoint

      – 通過 StreamingContext 的 checkpoint 來指定目錄

      – 通過 DStream 的 checkpoint 指定間隔時間

      – 間隔必須是 slide interval 的倍數

    2. 容錯
      DStream 基於 RDD 組成, RDD 的容錯性依舊有效
      1. RDD 的某些 partition 丟失了 , 可以通過 lineage 資訊重新計算恢復
      2. 資料來源來自外部檔案系統 , 如 HDFS
        1. 一定可以通過重新讀取資料來恢復 , 絕對不會有資料丟失
      3. 資料來源來自網路
        1. 預設會在兩個不同節點載入資料到記憶體 , 一個節點 fail 了 , 系統可以通過另一個節點的數 據重算 
        2. 假設正在執行 InputReceiver 的節點 fail 了 , 可能會丟失一部分資料

  6. 優化
    1. 監控手段
      一般來說,使用Spark自帶的Web UI就能滿足大部分的監控需求。對於Spark Streaming來說,以下幾個度量指標尤為重要(在Batch Processing Statistics標籤下): 
      • Processing Time:處理每個batch的時間 
      • Scheduling Delay:每個batch在佇列中等待前一個batch完成處理所等待的時間
      • 若Processing Time的值一直大於Scheduling Delay,或者Scheduling Delay的值持續增長,代表系統已經無法處理這樣大的資料輸入量了,這時就需要考慮各種優化方法來增強系統的負載。
    2. 優化方式
      1. 利用叢集資源,減少處理每個批次的資料的時間
        1.  控制 reduce 數量,太多的 reducer, 造成很多的小任務 , 以此產生很多啟動任務的開銷。太 少的 reducer, 任務執行行慢 ! 
          1. spark.streaming.blockInterval
          2. inputStream.repartition
          3. spark.default.parallelism
        2. 序列化
          1. 輸入資料序列化
          2. RDD 序列化
          3. TASK 序列化
      2. 在 Standalone 及 coarse-grained 模式下的任務啟動要比 fine-grained 省時
      3. 給每個批次的資料量的設定一個合適的大小,原則 : 要來得及消化流進系統的資料
      4. 記憶體調優
        1. 清理快取的 RDD
          1. 在 spark.cleaner.ttl 之前快取的 RDD 都會被清除掉
          2. 設定 spark.streaming.unpersis, 系統為你分憂
          3. 使用併發垃圾收集器
轉載: http://blog.csdn.net/eric_sunah/article/details/49762839

相關文章