Spark Streaming容錯機制以及事務語義詳解

北風網spark學習筆記

容錯機制的背景

  • 要理解Spark Streaming提供的容錯機制,先回憶一下Spark RDD的基礎容錯語義:
    1. RDD,Ressilient Distributed Dataset,是不可變的、確定的、可重新計算的、分佈式的數據集。每個RDD都會記住確定好的計算操作的血緣關係,(val lines = sc.textFile(hdfs file); val words = lines.flatMap(); val pairs = words.map(); val wordCounts = pairs.reduceByKey())這些操作應用在一個容錯的數據集上來創建RDD。
    2. 如果因爲某個Worker節點的失敗(掛掉、進程終止、進程內部報錯),導致RDD的某個partition數據丟失了,那麼那個partition可以通過對原始的容錯數據集應用操作血緣,來重新計算出來。
    3. 所有的RDD transformation操作都是確定的,最後一個被轉換出來的RDD的數據,一定是不會因爲Spark集羣的失敗而丟失的。
  • Spark操作的通常是容錯文件系統中的數據,比如HDFS。因此,所有通過容錯數據生成的RDD也是容錯的。然而,對於Spark Streaming來說,這卻行不通,因爲在大多數情況下,數據都是通過網絡接收的(除了使用fileStream數據源)。要讓Spark Streaming程序中,所有生成的RDD,都達到與普通Spark程序的RDD,相同的容錯性,接收到的數據必須被複制到多個Worker節點上的Executor內存中,默認的複製因子是2。
  • 基於上述理論,在出現失敗的事件時,有兩種數據需要被恢復:
    1. 數據接收到了,並且已經複製過——這種數據在一個Worker節點掛掉時,是可以繼續存活的,因爲在其他Worker節點上,還有它的一份副本。
    2. 數據接收到了,但是正在緩存中,等待複製的——因爲還沒有複製該數據,因此恢復它的唯一辦法就是重新從數據源獲取一份。
  • 此外,還有兩種失敗是我們需要考慮的:
    1. Worker節點的失敗——任何一個運行了Executor的Worker節點的掛掉,都會導致該節點上所有在內存中的數據都丟失。如果有Receiver運行在該Worker節點上的Executor中,那麼緩存的,待複製的數據,都會丟失。
    2. Driver節點的失敗——如果運行Spark Streaming應用程序的Driver節點失敗了,那麼顯然SparkContext會丟失,那麼該Application的所有Executor的數據都會丟失。

Spark Streaming容錯語義的定義

  • 流式計算系統的容錯語義,通常是以一條記錄能夠被處理多少次來衡量的。有三種類型的語義可以提供:
    1. 最多一次:每條記錄可能會被處理一次,或者根本就不會被處理。可能有數據丟失。
    2. 至少一次:每條記錄會被處理一次或多次,這種語義比最多一次要更強,因爲它確保零數據丟失。但是可能會導致記錄被重複處理幾次。
    3. 一次且僅一次:每條記錄只會被處理一次——沒有數據會丟失,並且沒有數據會處理多次。這是最強的一種容錯語義。

Spark Streaming的基礎容錯語義

  • 在Spark Streaming中,處理數據都有三個步驟:
    1. 接收數據:使用Receiver或其他方式接收數據。
    2. 計算數據:使用DStream的transformation操作對數據進行計算和處理。
    3. 推送數據:最後計算出來的數據會被推送到外部系統,比如文件系統、數據庫等。
  • 如果應用程序要求必須有一次且僅一次的語義,那麼上述三個步驟都必須提供一次且僅一次的語義。每條數據都得保證,只能接收一次、只能計算一次、只能推送一次。Spark
    Streaming中實心這些語義的步驟如下:
    1. 接收數據:不同的數據源提供不同的語義保障。
    2. 計算數據:所有接收到的數據一定只會被計算一次,這是基於RDD的基礎語義所保障的。即使有失敗,只要接收到的數據還是可訪問的,最後一個計算出來的數據一定是相同的。
    3. 推送數據:output操作默認能確保至少一次的語義,因爲它依賴於output操作的類型,以及底層系統的語義支持(比如是否有事務支持等),但是用戶可以實現它們自己的事務機制來確保一次且僅一次的語義。

接收數據的容錯語義

  • 基於文件的數據源

    如果所有的輸入數據都在一個容錯的文件系統中,比如HDFS,Spark Streaming一定可以從失敗進行恢復,並且處理所有數據。這就提供了一次且僅一次的語義,意味着所有的數據只會處理一次。

  • 基於Receiver的數據源

    對於基於Receiver的數據源,容錯語義依賴於失敗的場景和Receiver類型。

    可靠的Receiver:這種Receiver會在接收到了數據,並且將數據複製之後,對數據源執行確認操作。如果Receiver在數據接收和複製完成之前,就失敗了,那麼數據源對於緩存的數據會接收不到確認,此時,當Receiver重啓之後,數據源會重新發送數據,沒有數據會丟失。

    不可靠的Receiver:這種Receiver不會發送確認操作,因此當Worker或者Driver節點失敗的時候,可能會導致數據丟失。

  • 不同的Receiver,提供了不同的語義。如果Worker節點失敗了,那麼使用的是可靠的Receiver的話,沒有數據會丟失。使用的是不可靠的Receiver的話,接收到,但是還沒複製的數據,可能會丟失。如果Driver節點失敗的話,所有過去接收到的,和複製過緩存在內存中的數據,全部會丟失。

  • 要避免這種過去接收的所有數據都丟失的問題,Spark從1.2版本開始,引入了預寫日誌機制,可以將Receiver接收到的數據保存到容錯存儲中。如果使用可靠的Receiver,並且還開啓了預寫日誌機制,那麼可以保證數據零丟失。這種情況下,會提供至少一次的保障。(Kafka是可以實現可靠Receiver的)

    部署場景 Worker失敗 Driver失敗
    Spark 1.1以前的版本,或者是Spark 1.2以後版本,但是沒有開啓預寫日誌機制 1、不可靠Receiver,會導致緩存數據丟失 2、可靠的Receiver,可以保證數據零丟失 3、至少一次的語義 1、不可靠Receiver,緩存的數據全部丟失 2、任何Receiver,過去接收的所有數據全部丟失 3、沒有容錯語義
    Spark 1.2以後版本,並開啓了預寫日誌機制 1、可靠Receiver,零數據丟失 2、至少一次的語義 1、可靠Receiver和文件,零數據丟失
  • 從Spark 1.3版本開始,引入了新的Kafka Direct API,可以保證,所有從Kafka接收到的數據,都是一次且僅一次。基於該語義保障,如果自己再實現一次且僅一次語義的output操作,那麼就可以獲得整個Spark Streaming應用程序的一次且僅一次的語義。

輸出數據的容錯語義

  • output操作,比如foreachRDD,可以提供至少一次的語義。那意味着,當Worker節點失敗時,轉換後的數據可能會被寫入外部系統一次或多次。對於寫入文件系統來說,這還是可以接收的,因爲會覆蓋數據。但是要真正獲得一次且僅一次的語義,有兩個方法:

    1. 冪等更新:多次寫操作,都是寫相同的數據,例如saveAs系列方法,總是寫入相同的數據。
    2. 事務更新:所有的操作都應該做成事務的,從而讓寫入操作執行一次且僅一次。給每個batch的數據都賦予一個唯一的標識,然後更新的時候判定,如果數據庫中還沒有該唯一標識,那麼就更新,如果有唯一標識,那麼就不更新。
    dstream.foreachRDD { (rdd, time) =>
      rdd.foreachPartition { partitionIterator =>
        val partitionId = TaskContext.get.partitionId()
        val uniqueId = generateUniqueId(time.milliseconds, partitionId)
        // partitionId和foreachRDD傳入的時間,可以構成一個唯一的標識
      }
    }
    

    Storm的容錯語義

  • Storm首先,它可以實現消息的高可靠性,就是說,它有一個機制,叫做Acker機制,可以保證,如果消息處理失敗,那麼就重新發送。保證了,至少一次的容錯語義。但是光靠這個,還是不行,數據可能會重複。

  • Storm提供了非常非常完善的事務機制,可以實現一次且僅一次的事務機制。事務Topology、透明的事務Topology、非透明的事務Topology,可以應用各種各樣的情況。對實現一次且僅一次的這種語義的支持,做的非常非常好。用事務機制,可以獲得它內部提供的一個唯一的id,然後基於這個id,就可以實現,output操作,輸出,推送數據的時候,先判斷,該數據是否更新過,如果沒有的話,就更新;如果更新過,就不要重複更新了。

  • 所以,至少,在容錯 / 事務機制方面,我覺得Spark Streaming還有很大的空間可以發展。特別是對於output操作的一次且僅一次的語義支持!

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