這就是我為什麼要學習Flink的原因
知道大資料的同學也應該知道 Flink 吧,最近在中國的熱度比較高,在社群的推動下,Flink 技術棧在越來越多的公司開始得到應用。
Flink 到底火不火?
據不完全統計,Flink 在中國公司的採用情況(部分)
其中, 他們用 Flink 做了什麼?
- Alibaba 使用 Flink 的分支版本 Blink 來優化實時搜尋排名。eg: 當商品商家一個商品之後,實時計算引擎(Flink)在秒級別 build 商品索引,優化商品搜尋。
- 騰訊利用 Apache Flink 構建了一個內部平臺(Oceanus),以提高開發和操作實時應用程式的效率。
- 快手使用了 Apache Flink 搭建了一個實時監控平臺,監控短視訊和直播的質量。
- 利用 Apache Flink 構建了實時資料倉庫,用於即時分析運營活動效果及使用者短期興趣。
- 華為雲提供基於 Flink 的雲服務。
- 滴滴使用 Apache Flink支援了實時監控、實時特徵抽取、實時ETL等業務。
- Ebay 的監控平臺由 Flink 提供支援,可在指標和日誌流上計算上千條自定義報警規則。
- 愛立信使用 Flink 構建了一個實時異常檢測器,通過大型基礎設施進行機器學習。
- Uber 在 Apache Flink 上構建了基於 SQL 的開源流媒體分析平臺 AthenaX。
- Yelp 利用 Flink 為其資料聯結器生態系統和流處理基礎架構提供支援。
- 財富 500 強金融服務公司 Capital One 使用 Flink 進行實時活動監控和報警。
- ...
https://cwiki.apache.org/confluence/display/FLINK/Powered+by+Flink更多公司檢視點這裡。
上面我們看到很多公司在用 Flink,構建了不少的應用,接下來用資料說話,在Google Trends上檢視關鍵詞 ,看一下 Flink 的搜尋使用者畫像,如圖:
國內熱度一隻獨秀,中國的開發者對 Flink 的熱情更高。國內的公司更願意擁抱新鮮事物,用於嘗試。
回到百度指數,檢視 Flink 關鍵次在全國城市的搜尋熱度分佈。(額,資料可能不是很準確,大部分程式設計師可能不用百度搜索)
再回到 Google 搜尋,檢視相應資料。
浙江上榜是因為阿里,阿里的程式設計師為社群貢獻了 Blink 分支,後續會把一些優秀的特性合併到主分支上。
在這裡感謝默默付出的參與者們,正是你們的開源奉獻,才使得需求端(公司)能夠更多的把 Flink 應用到實際的業務中,提升業務水平。同時社群積極推進 Flink 相關課程培訓,培訓更多的 Flink 開發者,建設人才。
一個技術火不火?除了底層的設計框架之外,參與者的熱情也是一方面,大家願意學習它,願意使用它,更願意維護它。我想,開源的魅力大抵如此。
搬磚、搬磚,還在等什麼呢?
Flink 的相關基礎知識
官網的一段話,最準確的DenFination
Apache Flink is aframeworkanddistributed processing engineforstatefulcomputations overunbounded and boundeddata streams.
首先它是一個框架,框架的作用就是隱藏底層細節,使用起來更加簡單,讓二手手機號出售平臺地圖開發者更關注與業務的實現。其次他也是分散式的處理引擎,單機的處理能力有限,那就多節點計算,這就涉及到分散式,它解決了很多分散式計的問題。有狀態和有界無界的資料流,這裡先買個不做介紹。
接下里 介紹 Flink 最核心的三個語義,希望讀者可以深刻理解。
Stream, 翻譯過來是流,那 Data Steam 就是資料流。在 Flink 中,一切資料都是 Stream,分為 unbounded (無界)和 bounded(有界)。使用過 Hive 或 Mapreduce 或 mysql 的同學應該知道,資料存在 hdfs 或其他檔案系統上,並且是一個固定的大小,我們把這些資料稱為一批資料。使用過 Spark Streaming 或 Storm 的同學也應該知道資料來源源不斷的流入,流出,計算,這個過程的資料稱為資料流。但是在 Flink 裡,把批/流資料全部抽象成流,分為有界的流和無界的流。
注:這裡在語義上的把資料統一成流,更好的實現了流批統一,底層公共一套 API,這個後面會講到,看不明白沒關係。
State, 翻譯過來是狀態。它是一個有狀態的計算引擎,舉一個例子,我們要統計一個使用者最近一個小時的訪問次數, Flink 會在系統內部會把這個 count 值儲存成狀態,一直累加或刪除。狀態就像記憶,而且這個份記憶是儲存在自身的。
它的優勢:
- 多種狀態基礎型別:Flink 為多種不同的資料結構提供了相對應的狀態基礎型別,例如原子值(value),列表(list)以及對映(map)。開發者可以基於處理函式對狀態的訪問方式,選擇最高效、最適合的狀態基礎型別。
- 外掛化的State Backend:State Backend 負責管理應用程式狀態,並在需要的時候進行 checkpoint。Flink 支援多種 state backend,可以將狀態存在記憶體或者RocksDB。RocksDB 是一種高效的嵌入式、持久化鍵值儲存引擎。Flink 也支援外掛式的自定義 state backend 進行狀態儲存。
- 精確一次語義:Flink 的 checkpoint 和故障恢復演算法保證了故障發生後應用狀態的一致性。因此,Flink 能夠在應用程式發生故障時,對應用程式透明,不造成正確性的影響。
- 超大資料量狀態:Flink 能夠利用其非同步以及增量式的 checkpoint 演算法,儲存數 TB 級別的應用狀態。
- 可彈性伸縮的應用:Flink 能夠通過在更多或更少的工作節點上對狀態進行重新分佈,支援有狀態應用的分散式的橫向伸縮。
注: 使用 storm 或 spark streaming 計算累加值的最常用做法都是利用第三方儲存來做,比如使用 redis 來累加值。而 Flink 支援有狀態的計算,這個狀態自己保管。
Time時間。Flink 有三種時間,分別是 event time ,資料產生的時間。ingestion time 資料到達 Flink DateFlow 的時間。processing time 資料到達每個運算元的時間。
Flink 提供了豐富的時間語義支援。
- 事件時間模式:使用事件時間語義的流處理應用根據事件本身自帶的時間戳進行結果的計算。因此,無論處理的是歷史記錄的事件還是實時的事件,事件時間模式的處理總能保證結果的準確性和一致性。
- Watermark 支援:Flink 引入了 watermark 的概念,用以衡量事件時間進展。Watermark 也是一種平衡處理延時和完整性的靈活機制。
- 遲到資料處理:當以帶有 watermark 的事件時間模式處理資料流時,在計算完成之後仍會有相關資料到達。這樣的事件被稱為遲到事件。Flink 提供了多種處理遲到資料的選項,例如將這些資料重定向到旁路輸出(side output)或者更新之前完成計算的結果。
- 處理時間模式:除了事件時間模式,Flink 還支援處理時間語義。處理時間模式根據處理引擎的機器時鐘觸發計算,一般適用於有著嚴格的低延遲需求,並且能夠容忍近似結果的流處理應用。
注:Flink 為什麼引入了時間的概念呢?因為在 Flink 內部資料是流,需要有一個來度量流計算處理進度的標識。所以引入了時間這個概念。
接下來,我們來簡單瞭解下 Flink 的分層 API,在這一部分,本篇文章不會太深入,會在後面的文章中講解每一層的具體應用以及實現。
如圖,Flink 根據抽象程度分層了三層,提供了三種不同的 API。每一種 API 在簡潔性和表達力上有著不同的側重,並且針對不同的應用場景。
ProcessFunction是 Flink 所提供的最具表達力的介面。下面這個例子充分展現了KeyedProcessFunction
強大的表達力,也因此是一個實現相當複雜的介面。
/** * 將相鄰的 keyed START 和 END 事件相匹配並計算兩者的時間間隔 * 輸入資料為 Tuple2<String, String> 型別,第一個欄位為 key 值, * 第二個欄位標記 START 和 END 事件。 */ public static class StartEndDuration extends KeyedProcessFunction<String, Tuple2<String, String>, Tuple2<String, Long>> { private ValueState<Long> startTime; @Override public void open(Configuration conf) { // obtain state handle startTime = getRuntimeContext() .getState(new ValueStateDescriptor<Long>("startTime", Long.class)); } /** Called for each processed event. */ @Override public void processElement( Tuple2<String, String> in, Context ctx, Collector<Tuple2<String, Long>> out) throws Exception { switch (in.f1) { case "START": // set the start time if we receive a start event. startTime.update(ctx.timestamp()); // register a timer in four hours from the start event. ctx.timerService() .registerEventTimeTimer(ctx.timestamp() + 4 * 60 * 60 * 1000); break; case "END": // emit the duration between start and end event Long sTime = startTime.value(); if (sTime != null) { out.collect(Tuple2.of(in.f0, ctx.timestamp() - sTime)); // clear the state startTime.clear(); } default: // do nothing } } /** Called when a timer fires. */ @Override public void onTimer( long timestamp, OnTimerContext ctx, Collector<Tuple2<String, Long>> out) { // Timeout interval exceeded. Cleaning up the state. startTime.clear(); } }
DataStream API為許多通用的流處理操作提供了處理原語。DataStream API 支援 Java 和 Scala 語言,預先定義了例如map()
、reduce()
、aggregate()
等函式。你可以通過擴充套件實現預定義介面或使用 Java、Scala 的 lambda 表示式實現自定義的函式。
用過 spark 的同學看到這裡一定很熟悉。
下面的程式碼示例展示瞭如何捕獲會話時間範圍內所有的點選流事件,並對每一次會話的點選量進行計數。
// 網站點選 Click 的資料流 DataStream<Click> clicks = ... DataStream<Tuple2<String, Long>> result = clicks // 將網站點選對映為 (userId, 1) 以便計數 .map( // 實現 MapFunction 介面定義函式 new MapFunction<Click, Tuple2<String, Long>>() { @Override public Tuple2<String, Long> map(Click click) { return Tuple2.of(click.userId, 1L); } }) // 以 userId (field 0) 作為 key .keyBy(0) // 定義 30 分鐘超時的會話視窗 .window(EventTimeSessionWindows.withGap(Time.minutes(30L))) // 對每個會話視窗的點選進行計數,使用 lambda 表示式定義 reduce 函式 .reduce((a, b) -> Tuple2.of(a.f0, a.f1 + b.f1));
Flink 支援兩種關係型的 API,Table API 和 SQL。這兩個 API 都是批處理和流處理統一的 API,這意味著在無邊界的實時資料流和有邊界的歷史記錄資料流上,關係型 API 會以相同的語義執行查詢,併產生相同的結果。
SELECT userId, COUNT(*) FROM clicks GROUP BY SESSION(clicktime, INTERVAL '30' MINUTE), userId
Flink 架構優勢
最後,這幾點 Flink 的架構方面的設計,或許是你說服別人使用 Flink 的理由。
1、處理有界和無界的資料。任何型別的資料都可以形成一種事件流。信用卡交易、感測器測量、機器日誌、網站或移動應用程式上的使用者互動記錄,所有這些資料都形成一種流。
Flink 擅長處理無界和有界資料流,得益於精確的時間控制和狀態化。
2、部署靈活。Flink 集成了所有常見的叢集資源管理器,例如Hadoop YARN、Apache Mesos和Kubernetes,但同時也可以作為獨立叢集執行。
3、極高的可伸縮性。阿里去年雙十一的資料處理峰值 17億條/秒。
4、極致的流式處理效能。
如圖,資料經過計算,會被儲存在state中。這裡 Flink 做了優化,計算結果一開始儲存在記憶體中,如果超出一定大小,就會儲存在可高效訪問的磁碟結構中。也就是說,Flink 本地狀態儘可能的儲存在記憶體中。為了保證容錯和資料準確性,Flink 也會定期和非同步的把本地狀態進行持久化儲存來保證故障場景下精確一次的狀態一致性。(有點繞!其實就是解決分散式場景下資料不一致的問題)
Flink 穩定嗎?
Flink 非常注重流資料處理的可運維性。下面介紹 Flink 的故障恢復機制,並介紹其管理和監控應用的功能。
在分散式系統中,服務故障是常有的事,如何保證服務能夠7*24小時穩定執行?
就兩個需求:任務失敗了可以重啟;重啟之後還會和沒發生故障一樣。
Flink通過幾下多種機制維護應用可持續執行及其一致性:
- 檢查點的一致性: Flink的故障恢復機制是通過建立分散式應用服務狀態一致性檢查點實現的,當有故障產生時,應用服務會重啟後,再重新載入上一次成功備份的狀態檢查點資訊。結合可重放的資料來源,該特性可保證精確一次(exactly-once)的狀態一致性。
- 高效的檢查點: 如果一個狀態資訊很大,勢必會帶來延遲性,Flink採用非同步及增量的方式構建檢查點服務。
- 端到端的精確一次: Flink為某些特定的儲存支援了事務型輸出的功能,即使在發生故障的情況下,也能夠保證精確一次的輸出。
- 整合多種叢集管理服務: Flink已與多種叢集管理服務緊密整合,如Hadoop YARN,Mesos, 以及Kubernetes。當叢集中某個流程任務失敗後,一個新的流程服務會自動啟動並替代它繼續執行。
- 內建高可用服務: Flink內建了為解決單點故障問題的高可用性服務模組,此模組是基於Apache ZooKeeper技術實現的,Apache ZooKeeper是一種可靠的、互動式的、分散式協調服務元件。HA 啊
Flink 作為一個優秀的實時計算框架,不可能僅憑一篇文章就能全部講清楚,所以遵循循序漸進的原則,本文主要介紹一些了Flink在全球的趨勢,為什麼火,基礎語義,架構等基礎知識作為入門,更好的理解它的設計初衷,真正明白 Flink 到底好在哪?如果您看完本文能夠了解這些,點贊(再看)轉發走一波,謝謝支援。