天天看點

10分鐘入門Flink——了解Flink

作者:不焦躁的程式員

Flink入門系列文章主要是為了給想學習Flink的你建立一個大體上的架構,助力快速上手Flink。學習Flink最有效的方式是先入門了解架構和概念,然後邊寫代碼邊實踐,然後再把官網看一遍。

Flink入門分為四篇,第一篇是《了解Flink》,第二篇《架構和原理》,第三篇是《DataStream》,第四篇是《Table Api & SQL》。

官網位址https://nightlies.apache.org/flink/flink-docs-release-1.15/zh/

1、友情提示

前期入門Flink時,可以直接編寫通過idea編寫Flink程式,然後直接運作main方法,無需搭建環境。我碰到許多初次接觸Flink的同學,被各種環境搭建、送出作業、複雜概念給勸退了。前期最好的入門方式就是直接上手寫代碼,main方法跑demo,快速了解概念,等入門之後再去實踐叢集環境、各種作業送出、各種複雜概念。接下來正式進入主題。

2、大白話

說白了,Flink就是個實時處理資料任務的架構,這個架構幫助開發者執行資料處理的任務,讓開發者無需關心高可用、性能等問題。如果你有一些資料任務需要執行,比如資料監控、資料分析、資料同步,那就可以考慮使用Flink。所謂流計算就是對源源不斷的資料進行計算,中間的計算結果存放在記憶體或者外部存儲,這就是有狀态的流計算。

3、示例代碼

通過2段簡單的代碼,也能清晰的看到Flink已經做到了流批統一,同樣的功能,使用同樣的API和算子,大大減少開發者的工作量。

本文示例采用的Flink版本是15.4,代碼位址:https://github.com/yclxiao/flink-blog.git

3.1、詞頻統計-批資料

// 1. 建立執行環境
StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();
// 2. 讀取資料源
DataStream<String> textStream = env.fromCollection(Arrays.asList(
        "java,c++,php,java,spring",
        "hadoop,scala",
        "c++,jvm,html,php"
));
// 3. 資料轉換
DataStream<Tuple2<String, Integer>> wordCountStream = textStream
        // 對資料源的單詞進行拆分,每個單詞記為1,然後通過out.collect将資料發射到下遊算子
        .flatMap(new FlatMapFunction<String, Tuple2<String, Integer>>() {
                     @Override
                     public void flatMap(String value, Collector<Tuple2<String, Integer>> out) throws Exception {
                         for (String word : value.split(",")) {
                             out.collect(new Tuple2<>(word, 1));
                         }
                     }
                 }
        )
        // 對單詞進行分組
        .keyBy(value -> value.f0)
        // 對某個組裡的單詞的數量進行滾動相加統計
        .reduce((a, b) -> new Tuple2<>(a.f0, a.f1 + b.f1));
// 4. 資料輸出。位元組輸出到控制台
wordCountStream.print("WordCountBatch========").setParallelism(1);
// 5. 啟動任務
env.execute(WordCountBatch.class.getSimpleName());
           

3.2、詞頻統計-流資料

// 1. 建立執行環境
StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();
// 2. 讀取資料源
DataStream<String> textStream = env.socketTextStream("localhost", 9999, "\n");
// 3. 資料轉換
DataStream<Tuple2<String, Integer>> wordCountStream = textStream
        // 對資料源的單詞進行拆分,每個單詞記為1,然後通過out.collect将資料發射到下遊算子
        .flatMap(new FlatMapFunction<String, Tuple2<String, Integer>>() {
                     @Override
                     public void flatMap(String value, Collector<Tuple2<String, Integer>> out) throws Exception {
                         for (String word : value.split("\\s")) {
                             out.collect(new Tuple2<>(word, 1));
                         }
                     }
                 }
        )
        // 對單詞進行分組
        .keyBy(value -> value.f0)
        // 對某個組裡的單詞的數量進行滾動相加統計
        .reduce((a, b) -> new Tuple2<>(a.f0, a.f1 + b.f1));
// 4. 資料輸出。位元組輸出到控制台
wordCountStream.print("WordCountStream=======").setParallelism(1);
// 5. 啟動任務
env.execute(WordCountStream.class.getSimpleName());
           

4、什麼是Flink

Flink是一個架構和分布式處理引擎,用于對無邊界和有邊界的資料流進行有狀态的計算。Flink是原生的流處理系統,但也提供了批處理API,用于基于流式計算引擎處理批量資料的計算能力,真正實作了批流統一。

Flink支援有狀态的計算。在流式計算過程中将算子的中間結果儲存在記憶體或者檔案系統中,等下一個事件進入算子後可以從之前的狀态中擷取中間結果,以便計算目前的結果,進而無需每次都基于全部的原始資料來統計結果,極大地提升了系統性能。每一個具有一定複雜度的流計算應用都是有狀态的,任何運作基本業務邏輯的流處理應用都需要在一定時間記憶體儲所接受的事件或者中間結果。

10分鐘入門Flink——了解Flink

Flink支援事件時間。Flink除了支援處理時間外,還支援事件時間(Event Time),根據事件本身自帶的時間戳(事件的産生時間)進行結果的計算。這種基于事件驅動的機制使得事件即使亂序到達,Flink也能夠計算出精确的結果,保證了結果的準确性和一緻性。

Flink支援高可用性。Flink可以實作快速故障恢複、動态擴容、7×24小時運作流式應用等作業。Flink還支援在不丢失應用狀态的前提下更新作業的程式代碼。Flink可以将任務執行的快照儲存在存儲媒體上,當需要停機運維等操作時,下次啟動可以直接從事先儲存的快照恢複原有的計算狀态,使得任務繼續按照停機之前的狀态運作。

Flink吞吐量高。較高的吞吐量可以提高資源使用率,減小系統開銷。

Flink容錯性好。Flink的容錯機制是基于分布式快照實作的,通過CheckPoint機制儲存流處理作業某些時刻的狀态,當任務異常結束時,預設從最近一次儲存的完整快照處恢複任務。

Flink提供了不同層級的API。Flink為流處理和批處理提供了不同層級的API,每一種API在簡潔性和表達力上有着不同的側重,并且針對不同的應用場景,不同層級的API降低了系統耦合度。

10分鐘入門Flink——了解Flink

5、應用場景

事件驅動:根據到來的事件流觸發計算、狀态更新或其他外部動作。主要應用執行個體有反欺詐、異常檢測、基于規則的報警、業務流程監控等。

資料分析:從原始資料中提取有價值的資訊和名額,這些資訊和名額資料可以寫入外部資料庫系統或以内部狀态的形式維護。

資料管道:資料管道和ETL(Extract-Transform-Load,提取-轉換-加載)作業的用途相似,都可以轉換、豐富資料,并将其從某個存儲系統移動到另一個。與傳統的ETL不同的是,傳統的ETL是周期性的,而Flink是以持續流模式運作的。

6、主要元件

存儲層:Flink本身并沒有提供分布式檔案系統,是以Flink的分析大多依賴外部存儲。

排程層:Flink自帶一個簡易的資源排程器,稱為獨立排程器(Standalone)。若叢集中沒有任何資料總管,則可以使用自帶的獨立排程器。當然,Flink也支援在其他的叢集管理器上運作,包括Hadoop YARN、Apache Mesos等。

計算層:Flink的核心是一個對由很多計算任務組成的、運作在多個工作機器或者一個計算叢集上的應用進行排程、分發以及監控的計算引擎,為API工具層提供基礎服務。

工具層:在Flink Runtime的基礎上,Flink提供了面向流處理(DataStream API)和批處理(DataSetAPI)的不同計算接口,并在此接口上抽象出了不同的應用類型元件庫,例如基于流處理的CEP(複雜事件處理庫)、Table&SQL(結構化表處理庫)和基于批處理的Gelly(圖計算庫)、FlinkML(機器學習庫)、Table&SQL(結構化表處理庫)。

7、Flink程式設計模型

Flink的程式設計套路是固定的,他其實就是幫助開發者去執行一些列任務,開發者無需關注性能、高可用等棘手問題。

有界資料集:定義一個資料流的開始,也定義資料流的結束,就會産生有界資料集。

批處理:有界資料集的處理通常稱為批處理

無界資料集:定義一個資料流的開始,但沒有定義資料流的結束,就會産生無界資料集。無界資料集會無休止地産生新資料,是沒有邊界的。

流處理:對無界資料集的處理被稱為流處理。

有界和無界轉換:有界資料集與無界資料集其實是一個相對的概念。如果每間隔一分鐘、一小時、一天對資料進行一次計算,那麼認為這一段時間的資料相對是有界的。有界的流資料又可以一條一條地按照順序發送給計算引擎進行處理,在這種情況下可以認為資料是相對無界的。有界資料集與無界資料集可以互相轉換。Flink正是使用這種方式将有界資料集與無界資料集進行統一處理,進而将批處理和流處理統一在一套流式引擎中,能夠同時實作批處理與流處理任務。

8、Flink程式結構

構成:一個Flink應用程式由3部分構成,分别為Source、Transformation和Sink。

10分鐘入門Flink——了解Flink
10分鐘入門Flink——了解Flink
10分鐘入門Flink——了解Flink

程式設計固定套路:

  1. 建立執行環境
  2. 讀取源資料
  3. 轉換資料
  4. 輸出轉換結果
  5. 觸發任務執行

9、補充概念

9.1、什麼是算子

Flink提供了豐富的用于資料處理的函數,這些函數稱為算子。說白了就是Flink提供了一系列處理資料的函數給你調用。至于函數内部如何處理交換資料,使用者無需關心。

9.2、原生流處理和微批次差別

原生流處理:

10分鐘入門Flink——了解Flink

微批次處理:

10分鐘入門Flink——了解Flink

9.3、處理次數

處理次數分為:At-Most-Once、At-Least-Once、Exactly-Once。

At-Most-Once:每條資料最多被處理一次,會有丢失資料的可能。

At-Least-Once:每條資料至少被處理一次,保證資料不會丢失,但資料可能會被重複處理。

Exactly-Once:每條資料僅被處理一次,不會丢失資料,也不會重複處理。

Storm實作了At-Least-Once,可以對資料至少處理一次,但不能保證僅處理一次,這樣就會導緻資料重複處理的問題,是以針對計數類的需求可能會産生一些誤差;

Spark Streaming和Flink都實作了Exactly-Once,可以保證對資料僅處理一次,即每個記錄将被精确處理一次,資料不會丢失,并且不會重複處理。

10、結尾

本文首先以粗淺的概念和大白話講了什麼是Flink以及他的使用場景,然後給出了1個簡單demo。再到後面給出了一些大的概念架構。希望對你有幫助。