Spark Streaming狀態操作: updateStateByKey、mapWithState

在Spark Streaming中,DStream的轉換分爲有狀態和無狀態兩種。無狀態的操作,即當前批次的處理不依賴於先前批次的數據,如map()、flatMap()、filter()、reduceByKey()、groupByKey()等等;而有狀態的操作,即當前批次的處理需要依賴先前批次的數據,這樣的話,就需要跨批次維護狀態。

總結spark streaming中的狀態操作:updateStateByKey、mapWithState

updateStateByKey

對整個實時計算的所有時間間隔內產生的相關數據進行統計。 spark streaming 的解決方案是累加器,工作原理是定義一個類似全局的可更新的變量,每個 時間窗口內得到的統計值都累加到上個時間窗口得到的值,這樣整個累加值就是跨越多個時間間隔。
updateStateByKey 操作可以讓我們爲每個 key 維護一份 state,並持續不斷的更新該 state
  • 首先,要定義一個 state,可以是任意的數據類型;
  • 其次,要定義 state 更新函數(指定一個函數如何使用之前的 state 和新值來更新 state)。 對於每個 batchspark 都會爲每個之前已經存在的 key 去應用一次 state 更新函數,無論這個 key batch 中是否有新的數據。如果 state 更新函數返回 none,那麼 key 對應的 state 就會被刪除。 當然對於每個新出現的 key 也會執行 state 更新函數。
注意
updatestateBykey 要求必須開啓 checkpoint 機制。
updateStateByKey 返回的都是 DStream 類型。根據 updateFunc 這個函數來更新狀態。其中參數:Seq[V]是本次的數據類型,Option[S]是前次計算結果類型,本次計算結果類型也是 Option[S]。計算肯定需要 Partitioner。因爲 Hash 高效率且不做排序,默認 Partitioner 是 HashPartitoner。 由於 cogroup 會對所有數據進行掃描,再按 key 進行分組,所以性能上會有問題。特別是隨着時間的推移,這樣的計算到後面會越算越慢。
所以數據量大的計算、複雜的計算,都不建議使用 updateStateByKey
 

mapWithState

mapWithState從spark 1.6.0開始出現,可以看做是updateStateByKey的升級版,有一些updateStateByKey所沒有的特徵:

1、支持輸出只發生更新的狀態和全量狀態
mapWithState默認每個批次只會返回當前批次中有新數據的Key的狀態,也可返回全量狀態。updateStateByKey每個批次都會返回所有狀態。

2、內置狀態超時管理
內置狀態超時管理,可對超時的Key單獨處理。也可實現如會話超時(Session Timeout)的功能。在updateStateByKey中,如果要實現類似功能,需要大量編碼。

3、初始化狀態
可以選擇自定義的RDD來初始化狀態。

4、可以返回任何我們期望的類型
由mapWithState函數可知,可以返回任何我們期望的類型,而updateStateByKey做不到這一點。

5、性能更高
實現上,mapWithState只是增量更新,updateStateByKey每個批次都會對歷史全量狀態和當前增量數據進行cogroup合併,狀態較大時,性能較低。

 

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