1. 程式人生 > >超越Storm,SparkStreaming——Flink如何實現有狀態的計算

超越Storm,SparkStreaming——Flink如何實現有狀態的計算

file

流式計算分為無狀態和有狀態兩種情況。無狀態計算觀察每個獨立的事件,Storm就是無狀態的計算框架,每一條訊息來了以後和前後都沒有關係,一條是一條。比如我們接收電力系統感測器的資料,當電壓超過240v就報警,這就是無狀態的資料。但是如果我們需要同時判斷多個電壓,比如三相電路,我們判斷三相電都高於某個值,那麼就需要將狀態儲存,計算。因為這三條記錄是分別傳送過來的。

file

Storm需要自己實現有狀態的計算,比如藉助於自定義的記憶體變數或者redis等系統,保證低延遲的情況下自己去判斷實現有狀態的計算,但是Flink就不需要這樣,而且作為新一代的流處理系統,Flink非常重視。

一致性

其實就是訊息傳遞的正確性。在流處理中,一致性分為 3 個級別。

  • at-most-once:最多一次,可能會丟失。

  • at-least-once:最少一次,可能會重複,而計算的時候可能就會多次運算影響結果。

  • exactly-once:恰好保證一次,這樣得到的結果是最準確的。

最先保證 exactly-once 的系統(Storm Trident 和 Spark Streaming),但是在效能和表現力這兩個方面付出了很大的代價。為了保證 exactly-once,這些系統無法單獨地對每條記錄運用應用邏輯,而是同時處理多條(一批)記錄,保證對每一批的處理要麼全部成功,要麼全部失敗。這就導致在得到結果前, 必須等待一批記錄處理結束。因此,使用者經常不得不使用兩個流處理框架 (一個用來保證 exactly-once,另一個用來對每個元素做低延遲處理),結果使基礎設施更加複雜。

但是,Flink解決了這種問題。

檢查點機制

檢查點是 Flink 最有價值的創新之一,因為它使 Flink 可以保 證 exactly-once,並且不需要犧牲效能。

Flink 檢查點的核心作用是確保狀態正確,即使遇到程式中斷,也要正確。 記住這一基本點之後,我們用一個例子來看檢查點是如何執行的。Flink 為 使用者提供了用來定義狀態的工具。例如,以下這個 Scala 程式按照輸入記錄 的第一個欄位(一個字串)進行分組並維護第二個欄位的計數狀態。

val stream: DataStream[(String, Int)] = ... 
 
val counts: DataStream[(String, Int)] = stream   
.keyBy(record => record._1)   
.mapWithState((in: (String, Int), count: Option[Int]) =>     
  count match {       
  	case Some(c) => ( (in._1, c + in._2), Some(c + in._2) )       
  	case None => ( (in._1, in._2), Some(in._2) )     
})

該程式有兩個運算元:keyBy 運算元用來將記錄按照第一個元素(一個字串) 進行分組,根據該 key 將資料進行重新分割槽,然後將記錄再發送給下一個運算元:有狀態的 map 運算元(mapWithState)。 map 運算元在接收到每個元素後, 將輸入記錄的第二個欄位的資料加到現有總數中,再將更新過的元素髮射出去。

file

輸入流中的 6 條記錄被檢查點屏障 (checkpoint barrier)隔開,所有的 map 運算元狀態均為0(計數還未開始)。 所有 key 為 a 的記錄將被頂層的 map 運算元處理,所有 key 為 b 的記錄將被中間層的 map 運算元處理,所有 key 為 c 的記錄則將被底層的 map 運算元處理。

如果輸入流來自訊息傳輸系統Kafka,這個相互隔離的位置就是偏移量。

file

檢查點屏障像普通記錄一樣在運算元之間流動。當 map 運算元處理完前 3 條記錄 並收到檢查點屏障時,它們會將狀態以非同步的方式寫入穩定儲存.

file

當沒有出現故障時,Flink 檢查點的開銷極小,檢查點操作的速度由穩定儲存的可用頻寬決定。

如果檢查點操作失敗,Flink 會丟棄該檢查點並繼續正常執行,因為之後的 某一個檢查點可能會成功。

file

在這種情況下,Flink 會重新拓撲(可能會獲取新的執行資源),將輸入流 倒回到上一個檢查點,然後恢復狀態值並從該處開始繼續計算。

file

Flink 將輸入流倒回到上一個檢查點屏障的位置,同時恢復 map 運算元的狀態值。 然後,Flink 從此處開始重新處理。這樣做保證了在記錄被處理之後,map 運算元的狀 態值與沒有發生故障時的一致.

Flink 檢查點演算法的正式名稱是非同步屏障快照(asynchronous barrier snapshotting)。

儲存點

狀態版本控制

檢查點由 Flink 自動生成,用來在故障發生時重新處理記錄,從而修正狀 態。Flink 使用者還可以通過另一個特性有意識地管理狀態版本,這個特性叫作儲存點(savepoint)。

儲存點與檢查點的工作方式完全相同,只不過它由使用者通過 Flink 命令列工 具或者 Web 控制檯手動觸發,而不由 Flink 自動觸發,使用者可以從儲存點重啟作業,而不用從頭開始。對儲存點的另一種理解是,它在明確的時間點儲存應用程式狀態的版本。

file

在圖中,v.0 是某應用程式的一個正在執行的版本。我們分別在 t1 時刻和 t2 時刻觸發了儲存點。因此,可以在任何時候返回到這兩個時間點,並且重 啟程式。更重要的是,可以從儲存點啟動被修改過的程式版本。舉例來說, 可以修改應用程式的程式碼(假設稱新版本為 v.1),然後從t1 時刻開始執行 改動過的程式碼。

file

使用儲存點更新Flink 應用程式的版本。新版本可以從舊版本生成的一個 儲存點處開始執行.

端到端的一致性

file

在該應用程式架構中,有狀態的Flink 應用程式消費來自訊息佇列的資料, 然後將資料寫入輸出系統,以供查詢。

輸入資料來自Kafka,在將狀態內容傳送到輸出儲存系統的過程中,如何保證 exactly-once 呢?這 叫作端到端的一致性。本質上有兩種實現方法,用哪一種方法則取決於輸 出儲存系統的型別,以及應用程式的需求。

(1) 第一種方法是在 sink 環節緩衝所有輸出,並在 sink 收到檢查點記錄時, 將輸出“原子提交”到儲存系統。這種方法保證輸出儲存系統中只存在 有一致性保障的結果,並且不會出現重複的資料。從本質上說,輸出存 儲系統會參與 Flink 的檢查點操作。要做到這一點,輸出儲存系統需要 具備“原子提交”的能力。

(2) 第二種方法是急切地將資料寫入輸出儲存系統,同時牢記這些資料可能 是“髒”的,而且需要在發生故障時重新處理。如果發生故障,就需要將 輸出、輸入和 Flink 作業全部回滾,從而將“髒”資料覆蓋,並將已經寫 入輸出的“髒”資料刪除。注意,在很多情況下,其實並沒有發生刪除 操作。例如,如果新記錄只是覆蓋舊紀錄(而不是新增到輸出中),那麼 “髒”資料只在檢查點之間短暫存在,並且最終會被修正過的新資料覆蓋。

根據輸出儲存系統的型別,Flink 及與之對應的聯結器可以一起保證端到端 的一致性,並且支援多種隔離級別。

更多Flink相關文章:

Streaming-大資料的未來

實時計算大資料處理的基石-Google Dataflow

資料架構的未來——淺談流處理架構

穿梭時空的實時計算框架——Flink對時間的處理

Flink快速入門--安裝與示例執行

大資料實時處理的王者-Flink

更多實時計算,Flink,Kafka等相關技術博文,歡迎關注實時流式計算:

相關推薦

超越StormSparkStreaming——Flink如何實現狀態計算

流式計算分為無狀態和有狀態兩種情況。無狀態計算觀察每個獨立的事件,Storm就是無狀態的計算框架,每一條訊息來了以後和前後都沒有

關於解決 http 狀態碼200php 文件輸出但是不顯示模板文件的問題

color echo strong 狀態碼 clas font index index.php 查看 一 問題 給公司搭建一個在線測試站點之後,在瀏覽器地址欄輸入 "http://xxx.xxx.xxx/index.php",頁面什麽都沒顯示。調出瀏覽器的開發者工具查看,h

Struts2如何實現MVC與Spring MVC什麽不同?

lte result map span 處理 view app pin resolve    Struts2采用filter充當前端控制器處理請求,filter會根據Struts.xml的配置,將請求分發給不同的業務控制器Action,再由Action處理具體的業務邏輯。A

flink 狀態udf 引起血案一

場景 近期在做一個畫像的任務,sql實現的,當中有一個udf,會做非常多事情,包含將從redis讀出歷史值加權,並將中間結果和加權後的結果更新到redis。 大家都知道,flink 是能夠支援事件處理的。也就是能夠沒有時間的概念,那麼在聚合,jo

Apache Flink-資料流之上的狀態計算

官網給出的Flink應用場景圖: 1.狀態計算。 2.從上圖看出的應用場景有? -----事件驅動式的流處理 -----ETL管道 -----資料分析 3.一般性架構 從架構上來說與一般的流式架構沒有太大的不同,任務排程和資源管理可以放在我們熟悉的yarn上進

狀態應用(Session)到無狀態應用(JWT)以及 SSO 和 OAuth2

從有狀態應用(Session)到無狀態應用(JWT),以及 SSO 和 OAuth2 不管用哪種方式認證使用者,都可能被中間人攻擊竊取 SessionID 或 Token,從而發生 CSRF 攻擊。解決方式就是全站 HTTPS。現在 Let’s Encrypt 已經支援免費的萬用字元 HTT

一個Activity中多個Fragment個別fragment實現沉浸式狀態

                如上圖,同一個activity(NoActionBar)有多個fragment的情況下,只有"我的"模組需要設定為沉浸式的狀態列,而其他fragmen

Atitit spring註解事務的demo與程式碼說明 目錄 1.1. Spring框架中要如何實現事務?一個註解@EnableTransactionManagement 1 1.2. 事務管理

Atitit spring註解事務的demo與程式碼說明 目錄 1.1. Spring框架中,要如何實現事務?有一個註解,@EnableTransactionManagement 1 1.2. 事務管理  99.99999%都是使用了xml來配置的 1 1.3.

Python 協程gevent(yield阻塞greenlet)協程實現多工(規律的交替協作執行)

實現多工:程序消耗的資源最大,執行緒消耗的資源次之,協程消耗的資源最少(單執行緒)。 gevent實現協程,gevent是通過阻塞程式碼(例如網路延遲等)來自動切換要執行的任務,所以在進行IO密集型程式時(例如爬蟲),使用gevent可以提高效率(有效利用網路延遲的時間去執行其他任務)。 &

Java中多型的實現哪些要求?實現多型的關鍵技術?

多型指的是允許不同類的物件對同一訊息做出響應,即同一訊息可以根據傳送物件的不同而採用多種不同的行為方式(傳送訊息就是函式呼叫)。實現多型的方法是動態繫結( Dynamic Binding),動態繫結指的是在執行期間判斷所引用物件的實際型別,根據其實際的型別呼叫其相應的方法。

Java實現環的單向連結串列並判斷單向連結串列是否

有一個單向連結串列,連結串列當中有可能出現環,就像下圖這樣。我們如何判斷一個單向連結串列是否有環呢? 那麼第一步,我們先實現一個這樣的連結串列,接著再說如何判斷這樣的連結串列。 實現有環的單向連結串列 1、定義add(Node node)方法 /**

Recylerview網格佈局分割線的實現列表四周也分割線

關於RecylerView分割線的問題,當佈局形式為線性佈局LinearLayoutManager的時候, 官方提供了一個定義好的分割線類DividerItemDecoration,但是當佈局形式為網格佈局GridLayoutManager的時候,官方沒有提供分割線的相關類,

C語言實現一個字元陣列的內容為:"student a am i"請你將陣列的內容改為"i am a student"。

//有一個字元陣列的內容為:"student a am i",請你將陣列的內容改為"i am a student"。    要求:不能使用庫函式。               只能開闢有限個空間(空間個數和字串的長度無關)。   解題思路:               

sort函式的用法(C++排序庫函式的呼叫)對陣列進行排序在c++中庫函式幫我們實現這們就不需要我們自己來程式設計進行排序了。

對陣列進行排序,在c++中有庫函式幫我們實現,這們就不需要我們自己來程式設計進行排序了。 (一)為什麼要用c++標準庫裡的排序函式 Sort()函式是c++一種排序方法之一,學會了這種方法也打消我學習c++以來使用的氣泡排序和選擇排序所帶來的執行效率不高的問題!因為它使用

已知一個抽象類Shapge該類中一個方法GetArea。 要求定義一個Rectangle類繼承Shape類實現GetArea方法計算矩形面積。

已知一個抽象類Shapge,該類中有一個方法GetArea。 要求定義一個Rectangle類,繼承Shape類,實現GetArea方法計算矩形面積。 輸入輸出說明: 輸入: 5 4 輸

SparkStreaming部分:OutPutOperator類SaveAsHadoopFile運算元(實際上底層呼叫textFileStream讀取的跟前兩種一些區別)【Java版純程式碼】

package streamingOperate.output; import java.util.Arrays; import org.apache.hadoop.io.IntWritable; import org.apache.hadoop.io.Text; imp

了html頁面進行二次顯示通過html、JavaScript、jQuery的ajax三種技術我可以實現任何介面效果

當前j2ee的web工程開發, 最常用的前端顯示技術,有兩種:html、jsp。 場景: 以html為例,當用戶執行了某個操作,j2ee的web工程反饋了一個html頁面給使用者(其實不是這麼簡單,中間有渲染的過程,這裡略過,就當使用者得到了一個html頁面)。例如點選“新

vue專案使用者登入狀態管理vuex+localStorage實現

一、實現思路1.利用localStorage本地儲存使用者登入狀態token2.在vuex中封裝localStorage操作,因為vue是SPA應用, 直接使用localStorage操作資料,無法監聽資料改變。3.在App.vue生命週期鉤子函式中呼叫登入介面,驗證使用者登

一個類所實現的兩個不同的介面中同名的方法怎麼知道實現的是哪個介面中的方法

今天遇到一個問題,程式碼(後面各個版本的程式碼都是基於此程式碼進行變更的)如下: public interface Type1 { void f(); void f1(); void f11(); } public interface Type2 { void f(); void f

SparkStreaming部分的學習(包括:sparkStreamingstorm的區別 Sparkstreaming處理資料的過程等)【業務邏輯圖及文字說明】

sparkStreaming與storm的區別:  Sparkstreaming處理資料的過程: sparkstreaming:資料是一段時間處理的,是一個微批處理,這個時間是由自己人為設定的。sparkstreaming的吞吐量高。 Storm:是純實時處理資料的,