1. 程式人生 > 其它 >大資料面試題解析之資料處理篇-Flink

大資料面試題解析之資料處理篇-Flink

1.Flink基礎

1. 簡單介紹一下 Flink

Flink 是一個框架和分散式處理引擎,用於對無界和有界資料流進行有狀態計算。並且 Flink 提供了資料分佈、容錯機制以及資源管理等核心功能。Flink提供了諸多高抽象層的API以便使用者編寫分散式任務:

DataSet API, 對靜態資料進行批處理操作,將靜態資料抽象成分散式的資料集,使用者可以方便地使用Flink提供的各種操作符對分散式資料集進行處理,支援Java、Scala和Python。

DataStream API,對資料流進行流處理操作,將流式的資料抽象成分散式的資料流,使用者可以方便地對分散式資料流進行各種操作,支援Java和Scala。

Table API,對結構化資料進行查詢操作,將結構化資料抽象成關係表,並通過類SQL的DSL對關係表進行各種查詢操作,支援Java和Scala。

此外,Flink 還針對特定的應用領域提供了領域庫,例如: Flink ML,Flink 的機器學習庫,提供了機器學習Pipelines API並實現了多種機器學習演算法。 Gelly,Flink 的圖計算庫,提供了圖計算的相關API及多種圖計算演算法實現。

2. Flink相比傳統的Spark Streaming區別?

這個問題是一個非常巨集觀的問題,因為兩個框架的不同點非常之多。但是在面試時有非常重要的一點一定要回答出來:Flink 是標準的實時處理引擎,基於事件驅動。而 Spark Streaming 是微批(Micro-Batch)的模型。

下面我們就分幾個方面介紹兩個框架的主要區別:

  1. 架構模型Spark Streaming 在執行時的主要角色包括:Master、Worker、Driver、Executor,Flink 在執行時主要包含:Jobmanager、Taskmanager和Slot。

  2. 任務排程Spark Streaming 連續不斷的生成微小的資料批次,構建有向無環圖DAG,Spark Streaming 會依次建立 DStreamGraph、JobGenerator、JobScheduler。Flink 根據使用者提交的程式碼生成 StreamGraph,經過優化生成 JobGraph,然後提交給 JobManager進行處理,JobManager 會根據 JobGraph 生成 ExecutionGraph,ExecutionGraph 是 Flink 排程最核心的資料結構,JobManager 根據 ExecutionGraph 對 Job 進行排程。

  3. 時間機制Spark Streaming 支援的時間機制有限,只支援處理時間。 Flink 支援了流處理程式在時間上的三個定義:處理時間、事件時間、注入時間。同時也支援 watermark 機制來處理滯後資料。

  4. 容錯機制對於 Spark Streaming 任務,我們可以設定 checkpoint,然後假如發生故障並重啟,我們可以從上次 checkpoint 之處恢復,但是這個行為只能使得資料不丟失,可能會重複處理,不能做到恰好一次處理語義。Flink 則使用兩階段提交協議來解決這個問題。

3. Flink的元件棧有哪些?

根據 Flink 官網描述,Flink 是一個分層架構的系統,每一層所包含的元件都提供了特定的抽象,用來服務於上層元件。

自下而上,每一層分別代表:Deploy 層:該層主要涉及了Flink的部署模式,在上圖中我們可以看出,Flink 支援包括local、Standalone、Cluster、Cloud等多種部署模式。Runtime 層:Runtime層提供了支援 Flink 計算的核心實現,比如:支援分散式 Stream 處理、JobGraph到ExecutionGraph的對映、排程等等,為上層API層提供基礎服務。API層:API 層主要實現了面向流(Stream)處理和批(Batch)處理API,其中面向流處理對應DataStream API,面向批處理對應DataSet API,後續版本,Flink有計劃將DataStream和DataSet API進行統一。Libraries層:該層稱為Flink應用框架層,根據API層的劃分,在API層之上構建的滿足特定應用的實現計算框架,也分別對應於面向流處理和麵向批處理兩類。面向流處理支援:CEP(複雜事件處理)、基於SQL-like的操作(基於Table的關係操作);面向批處理支援:FlinkML(機器學習庫)、Gelly(圖處理)。

4.Flink 的執行必須依賴 Hadoop元件嗎?

Flink可以完全獨立於Hadoop,在不依賴Hadoop元件下執行。但是做為大資料的基礎設施,Hadoop體系是任何大資料框架都繞不過去的。Flink可以整合眾多Hadooop 元件,例如Yarn、Hbase、HDFS等等。例如,Flink可以和Yarn整合做資源排程,也可以讀寫HDFS,或者利用HDFS做檢查點。

5. 你們的Flink叢集規模多大?

大家注意,這個問題看起來是問你實際應用中的Flink叢集規模,其實還隱藏著另一個問題:Flink可以支援多少節點的叢集規模?在回答這個問題時候,可以將自己生產環節中的叢集規模、節點、記憶體情況說明,同時說明部署模式(一般是Flink on Yarn),除此之外,使用者也可以同時在小叢集(少於5個節點)和擁有 TB 級別狀態的上千個節點上執行 Flink 任務。

6. Flink的基礎程式設計模型瞭解嗎?

上圖是來自Flink官網的執行流程圖。通過上圖我們可以得知,Flink 程式的基本構建是資料輸入來自一個 Source,Source 代表資料的輸入端,經過 Transformation 進行轉換,然後在一個或者多個Sink接收器中結束。資料流(stream)就是一組永遠不會停止的資料記錄流,而轉換(transformation)是將一個或多個流作為輸入,並生成一個或多個輸出流的操作。執行時,Flink程式對映到 streaming dataflows,由流(streams)和轉換操作(transformation operators)組成。

7. Flink叢集有哪些角色?各自有什麼作用?

Flink 程式在執行時主要有 TaskManager,JobManager,Client三種角色。其中

  • JobManager扮演著叢集中的管理者Master的角色,它是整個叢集的協調者,負責接收Flink Job,協調檢查點,Failover 故障恢復等,同時管理Flink叢集中從節點TaskManager。

  • TaskManager是實際負責執行計算的Worker,在其上執行Flink Job的一組Task,每個TaskManager負責管理其所在節點上的資源資訊,如記憶體、磁碟、網路,在啟動的時候將資源的狀態向JobManager彙報。

  • Client是Flink程式提交的客戶端,當用戶提交一個Flink程式時,會首先建立一個Client,該Client首先會對使用者提交的Flink程式進行預處理,並提交到Flink叢集中處理,所以Client需要從使用者提交的Flink程式配置中獲取JobManager的地址,並建立到JobManager的連線,將Flink Job提交給JobManager。

8. 說說 Flink 資源管理中 Task Slot 的概念

在Flink架構角色中我們提到,TaskManager是實際負責執行計算的Worker,TaskManager 是一個 JVM 程序,並會以獨立的執行緒來執行一個task或多個subtask。為了控制一個 TaskManager 能接受多少個 task,Flink 提出了 Task Slot 的概念。簡單的說,TaskManager會將自己節點上管理的資源分為不同的Slot:固定大小的資源子集。這樣就避免了不同Job的Task互相競爭記憶體資源,但是需要主要的是,Slot只會做記憶體的隔離。沒有做CPU的隔離。

9. 說說 Flink 的常用運算元?

Flink 最常用的常用運算元包括:Map:DataStream → DataStream,輸入一個引數產生一個引數,map的功能是對輸入的引數進行轉換操作。Filter:過濾掉指定條件的資料。KeyBy:按照指定的key進行分組。Reduce:用來進行結果彙總合併。Window:視窗函式,根據某些特性將每個key的資料進行分組(例如:在5s內到達的資料)

10. 你知道的Flink分割槽策略?

什麼要搞懂什麼是分割槽策略。分割槽策略是用來決定資料如何傳送至下游。目前 Flink 支援了8種分割槽策略的實現。

上圖是整個Flink實現的分割槽策略繼承圖:

GlobalPartitioner資料會被分發到下游運算元的第一個例項中進行處理。

ShufflePartitioner資料會被隨機分發到下游運算元的每一個例項中進行處理。

RebalancePartitioner 資料會被迴圈傳送到下游的每一個例項中進行處理。

RescalePartitioner這種分割槽器會根據上下游運算元的並行度,迴圈的方式輸出到下游運算元的每個例項。這裡有點難以理解,假設上游並行度為2,編號為A和B。下游並行度為4,編號為1,2,3,4。那麼A則把資料迴圈傳送給1和2,B則把資料迴圈傳送給3和4。假設上游並行度為4,編號為A,B,C,D。下游並行度為2,編號為1,2。那麼A和B則把資料傳送給1,C和D則把資料傳送給2。

BroadcastPartitioner廣播分割槽會將上游資料輸出到下游運算元的每個例項中。適合於大資料集和小資料集做Jion的場景。

ForwardPartitioner用於將記錄輸出到下游本地的運算元例項。它要求上下游運算元並行度一樣。簡單的說,ForwardPartitioner用來做資料的控制檯列印。

KeyGroupStreamPartitioner Hash分割槽器。會將資料按 Key 的 Hash 值輸出到下游運算元例項中。CustomPartitionerWrapper 使用者自定義分割槽器。需要使用者自己實現Partitioner介面,來定義自己的分割槽邏輯。例如:

static class CustomPartitioner implements Partitioner<String> {
@Override
publicintpartition(String key, int numPartitions) {
switch (key){
case "1":
return 1;
case "2":
return 2;
case "3":
return 3;
default:
return 4;
}
}
}