Flink的應用場景和架構

Flink的應用場景

Flink項目的理念就是:Flink是為分散式,高性能,隨時可用以及準確的流處理應用程式打造的開源流處理框架。自2019年開源以來,迅速成為大數據實時計算領域炙手可熱的技術框架。

我們來看看Flink支援的眾多應用場景:

實時數據計算

我們知道,數據計算場景需要從原始數據中提取有價值的資訊和指標,比如天貓雙十一的實時監控大屏,公司想看大促中銷量最好的商品Top5,以及伺服器的負載情況等。

傳統的分析方式通常是利用批查詢,或將事件(生產上一般是消息)記錄下來並基於此形成有限數據集(表)構建應用來完成。為了得到最新數據的計算結果,必須先將它們寫入表中並重新執行 SQL 查詢,然後將結果寫入存儲系統比如 MySQL 中,再生成報告。

Apache Flink同時支援流處理和批處理,這就是我們說的流批一體。Flink在上述的需求場景中承擔了數據的實時採集、實時計算和下游發送。

實時數據倉庫和ETL

ETL的目的是將業務系統的數據經過抽取、清洗轉換後載入到數倉的過程。

傳統的離線數據倉庫將業務數據集中進行存儲後,以固定的計算邏輯定時進行 ETL 和其他建模後產出報表等應用。離線數據倉庫主要是構建 T+1 的離線數據,通過定時任務每天拉取增量數據,然後創建各個業務相關的主題維度數據,對外提供 T+1 的數據查詢介面。

上圖展示了離線數據倉庫 ETL 和實時數據倉庫的差異,可以看到離線數據倉庫的計算和數據的實時性均較差。數據本身的價值隨著時間的流逝會逐步減弱,因此數據發生後必須儘快的達到用戶的手中,實時數倉的構建需求也應運而生。

Flink 在實時數倉和實時 ETL 中有天然的優勢:

  • 狀態管理,實時數倉裡面會進行很多的聚合計算,這些都需要對於狀態進行訪問和管理,Flink 支援強大的狀態管理;
  • 豐富的 API,Flink 提供極為豐富的多層次 API,包括 Stream API、Table API 及 Flink SQL;
  • 生態完善,實時數倉的用途廣泛,Flink 支援多種存儲(HDFS、ES 等);
  • 批流一體,Flink 已經在將流計算和批計算的 API 進行統一。

事件驅動型應用

事件驅動型應用是一類具有狀態的應用,它從一個或多個事件流提取數據,並根據到來的事件觸發計算、狀態更新或其他外部動作。

在傳統架構中,我們需要讀寫遠程事務型資料庫,比如 MySQL。在事件驅動應用中數據和計算不會分離,應用只需訪問本地(記憶體或磁碟)即可獲取數據,所以具有更高的吞吐和更低的延遲。

Flink 的以下特性完美的支援了事件驅動型應用:

  • 高效的狀態管理,Flink 自帶的 State Backend 可以很好的存儲中間狀態資訊;

  • 豐富的窗口支援,Flink 支援包含滾動窗口、滑動窗口及其他窗口;

  • 多種時間語義,Flink 支援 Event Time、Processing Time 和 Ingestion Time;

  • 不同級別的容錯,Flink 支援 At Least Once 或 Exactly Once 容錯級別。

小結

Apache Flink 從底層支援了針對多種不同場景的應用開發。

Flink 的主要特性包括:批流一體、Exactly-Once、強大的狀態管理等。同時,Flink 還支援運行在包括 YARN、 Mesos、Kubernetes 在內的多種資源管理框架上。阿里巴巴已經率先將 Flink 在全集團進行推廣使用,事實證明,Flink 已經可以擴展到數千核心,其狀態可以達到 TB 級別,且仍能保持高吞吐、低延遲的特性。

Flink的架構模型

Flink的分層模型

Flink 自身提供了不同級別的抽象來支援我們開發流式或者批量處理程式,上圖描述了 Flink 支援的 4 種不同級別的抽象。

對於我們開發者來說,大多數應用程式不需要上圖中的最低級別的 Low-level 抽象,而是針對 Core API 編程, 比如 DataStream API(有界/無界流)和 DataSet API (有界數據集)。這些流暢的 API 提供了用於數據處理的通用構建塊,比如各種形式用戶指定的轉換、連接、聚合、窗口、狀態等。

Table API 和 SQL 是 Flink 提供的更為高級的 API 操作,Flink SQL 是 Flink 實時計算為簡化計算模型,降低用戶使用實時計算門檻而設計的一套符合標準 SQL 語義的開發語言。

Flink 程式的基礎構建模組是流(Streams)與轉換(Transformations),每一個數據流起始於一個或多個 Source,並終止於一個或多個 Sink。數據流類似於有向無環圖(DAG)。

我們以一個最經典的 WordCount 計數程式舉例:

img

在上圖中,程式消費 Kafka 數據,這便是我們的 Source 部分。

然後經過 Map、Keyby、TimeWindow 等方法進行邏輯計算,該部分就是我們的 Transformation 轉換部分,而其中的 Map、Keyby、TimeWindow 等方法被稱為運算元。通常,程式中的轉換與數據流中的運算元之間存在對應關係,有時一個轉換可能包含多個轉換運算元。

最後,經過計算的數據會被寫入到我們執行的文件中,這便是我們的 Sink 部分。

實際上面對複雜的生產環境,Flink 任務大都是並行進行和分布在各個計算節點上。在 Flink 任務執行期間,每一個數據流都會有多個分區,並且每個運算元都有多個運算元任務並行進行。運算元子任務的數量是該特定運算元的並行度(Parallelism),對並行度的設置是 Flink 任務進行調優的重要手段。

img

從上圖中可以看到,在上面的 map 和 keyBy/window 之間,以及 keyBy/window 和 Sink 之間,因為並行度的差異,數據流都進行了重新分配。

窗口和時間是 Flink 中的核心概念之一。在實際成產環境中,對數據流上的聚合需要由窗口來劃定範圍,比如「計算過去的 5 分鐘」或者「最後 100 個元素的和」。

Flink 支援了多種窗口模型比如滾動窗口(Tumbling Window)、滑動窗口(Sliding Window)及會話窗口(Session Window)等。

下圖展示了 Flink 支援的多種窗口模型:

img

同時,Flink 支援了事件時間(Event Time)、攝取時間(Ingestion Time)和處理時間(Processing Time)三種時間語義用來滿足實際生產中對於時間的特殊需求。

img

Flink 作為實時計算領域的一匹黑馬,先進的設計思想、強大的性能和豐富的業務場景支援,已經是我們開發者必須要學習的技能之一,Flink 已經成為實時計算領域最鋒利的武器!