Flink 面試通關手冊

概述

2019 年是大數據實時計算領域最不平凡的一年,2019 年 1 月阿里巴巴 Blink (內部的 Flink 分支版本)開源,大數據領域一晚上間從 Spark 獨步天下走向了兩強爭霸的時代。Flink 由於其自然的流式計算特性以及強大的處理性能成爲煊赫一時的大數據處理框架。java

時至今日,Flink 已經發展到 1.9 版本,在大數據開發領域,面試中對於 Flink 的考察已是大數據開發求職者必須面對的,本文結合本身做爲面試官過程當中的經驗詳細總結了近 50 個關於 Flink 的面試考察點。git

在本場 Chat 中,分爲如下幾個部分:面試

第一部分:Flink 中的核心概念和基礎篇,包含了 Flink 的總體介紹、核心概念、算子等考察點。算法

第二部分:Flink 進階篇,包含了 Flink 中的數據傳輸、容錯機制、序列化、數據熱點、反壓等實際生產環境中遇到的問題等考察點。apache

第三部分:Flink 源碼篇,包含了 Flink 的核心代碼實現、Job 提交流程、數據交換、分佈式快照機制、Flink SQL 的原理等考察點。編程

第一部分:Flink 中的核心概念和基礎考察

1、 簡單介紹一下 Flink segmentfault

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及多種圖計算算法實現。性能優化

根據官網的介紹,Flink 的特性包含:

支持高吞吐、低延遲、高性能的流處理
支持帶有事件時間的窗口 (Window) 操做
支持有狀態計算的 Exactly-once 語義
支持高度靈活的窗口 (Window) 操做,支持基於 time、count、session 以及 data-driven 的窗口操做
支持具備 Backpressure 功能的持續流模型
支持基於輕量級分佈式快照(Snapshot)實現的容錯
一個運行時同時支持 Batch on Streaming 處理和 Streaming 處理
Flink 在 JVM 內部實現了本身的內存管理
支持迭代計算
支持程序自動優化:避免特定狀況下 Shuffle、排序等昂貴操做,中間結果有必要進行緩存

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 是一個分層架構的系統,每一層所包含的組件都提供了特定的抽象,用來服務於上層組件。

file
圖片來源於:https://flink.apache.org

自下而上,每一層分別表明:
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的基礎編程模型瞭解嗎?

file
上圖是來自Flink官網的運行流程圖。
經過上圖咱們能夠得知,Flink 程序的基本構建是數據輸入來自一個 Source,Source 表明數據的輸入端,通過 Transformation 進行轉換,而後在一個或者多個Sink接收器中結束。數據流(stream)就是一組永遠不會中止的數據記錄流,而轉換(transformation)是將一個或多個流做爲輸入,並生成一個或多個輸出流的操做。執行時,Flink程序映射到 streaming dataflows,由流(streams)和轉換操做(transformation operators)組成。

7、Flink集羣有哪些角色?各自有什麼做用?

file

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 的概念

file

在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中分區策略的實現。

file

上圖是整個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 用於將記錄輸出到下游本地的算子實例。它要求上下游算子並行度同樣。
簡單的說,ForwardPartitioner用來作數據的控制檯打印。

KeyGroupStreamPartitioner
Hash分區器。會將數據按 Key 的 Hash 值輸出到下游算子實例中。

CustomPartitionerWrapper
用戶自定義分區器。須要用戶本身實現Partitioner接口,來定義本身的分區邏輯。
例如:

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

11、Flink的並行度瞭解嗎?Flink的並行度設置是怎樣的?

Flink中的任務被分爲多個並行任務來執行,其中每一個並行的實例處理一部分數據。這些並行實例的數量被稱爲並行度。

咱們在實際生產環境中能夠從四個不一樣層面設置並行度:

  • 操做算子層面(Operator Level)
  • 執行環境層面(Execution Environment Level)
  • 客戶端層面(Client Level)
  • 系統層面(System Level)

須要注意的優先級:算子層面>環境層面>客戶端層面>系統層面。

12、Flink的Slot和parallelism有什麼區別?

官網上十分經典的圖:

file

slot是指taskmanager的併發執行能力,假設咱們將 taskmanager.numberOfTaskSlots 配置爲3
那麼每個 taskmanager 中分配3個 TaskSlot, 3個 taskmanager 一共有9個TaskSlot。

file

parallelism是指taskmanager實際使用的併發能力。假設咱們把 parallelism.default 設置爲1,那麼9個 TaskSlot 只能用1個,有8個空閒。

十3、Flink有沒有重啓策略?說說有哪幾種?

Flink 實現了多種重啓策略。

  • 固定延遲重啓策略(Fixed Delay Restart Strategy)
  • 故障率重啓策略(Failure Rate Restart Strategy)
  • 沒有重啓策略(No Restart Strategy)
  • Fallback重啓策略(Fallback Restart Strategy)

十4、用過Flink中的分佈式緩存嗎?如何使用?

Flink實現的分佈式緩存和Hadoop有殊途同歸之妙。目的是在本地讀取文件,並把他放在 taskmanager 節點中,防止task重複拉取。

val env = ExecutionEnvironment.getExecutionEnvironment

// register a file from HDFS
env.registerCachedFile("hdfs:///path/to/your/file", "hdfsFile")

// register a local executable file (script, executable, ...)
env.registerCachedFile("file:///path/to/exec/file", "localExecFile", true)

// define your program and execute
...
val input: DataSet[String] = ...
val result: DataSet[Integer] = input.map(new MyMapper())
...
env.execute()

十5、說說Flink中的廣播變量,使用時須要注意什麼?

咱們知道Flink是並行的,計算過程可能不在一個 Slot 中進行,那麼有一種狀況即:當咱們須要訪問同一份數據。那麼Flink中的廣播變量就是爲了解決這種狀況。

咱們能夠把廣播變量理解爲是一個公共的共享變量,咱們能夠把一個dataset 數據集廣播出去,而後不一樣的task在節點上都可以獲取到,這個數據在每一個節點上只會存在一份。

十6、說說Flink中的窗口?

來一張官網經典的圖:
file

Flink 支持兩種劃分窗口的方式,按照time和count。若是根據時間劃分窗口,那麼它就是一個time-window 若是根據數據劃分窗口,那麼它就是一個count-window。

flink支持窗口的兩個重要屬性(size和interval)

若是size=interval,那麼就會造成tumbling-window(無重疊數據)
若是size>interval,那麼就會造成sliding-window(有重疊數據)
若是size< interval, 那麼這種窗口將會丟失數據。好比每5秒鐘,統計過去3秒的經過路口汽車的數據,將會漏掉2秒鐘的數據。

經過組合能夠得出四種基本窗口:

  • time-tumbling-window 無重疊數據的時間窗口,設置方式舉例:timeWindow(Time.seconds(5))
  • time-sliding-window 有重疊數據的時間窗口,設置方式舉例:timeWindow(Time.seconds(5), Time.seconds(3))
  • count-tumbling-window無重疊數據的數量窗口,設置方式舉例:countWindow(5)
  • count-sliding-window 有重疊數據的數量窗口,設置方式舉例:countWindow(5,3)

十7、說說Flink中的狀態存儲?

Flink在作計算的過程當中常常須要存儲中間狀態,來避免數據丟失和狀態恢復。選擇的狀態存儲策略不一樣,會影響狀態持久化如何和 checkpoint 交互。

Flink提供了三種狀態存儲方式:MemoryStateBackend、FsStateBackend、RocksDBStateBackend。

十8、Flink 中的時間有哪幾類

Flink 中的時間和其餘流式計算系統的時間同樣分爲三類:事件時間,攝入時間,處理時間三種。

若是以 EventTime 爲基準來定義時間窗口將造成EventTimeWindow,要求消息自己就應該攜帶EventTime。
若是以 IngesingtTime 爲基準來定義時間窗口將造成 IngestingTimeWindow,以 source 的systemTime爲準。
若是以 ProcessingTime 基準來定義時間窗口將造成 ProcessingTimeWindow,以 operator 的systemTime 爲準。

十9、Flink 中水印是什麼概念,起到什麼做用?

Watermark 是 Apache Flink 爲了處理 EventTime 窗口計算提出的一種機制, 本質上是一種時間戳。
通常來說Watermark常常和Window一塊兒被用來處理亂序事件。

二10、Flink Table & SQL 熟悉嗎?TableEnvironment這個類有什麼做用

TableEnvironment是Table API和SQL集成的核心概念。

這個類主要用來:

  • 在內部catalog中註冊表
  • 註冊外部catalog
  • 執行SQL查詢
  • 註冊用戶定義(標量,表或聚合)函數
  • 將DataStream或DataSet轉換爲表
  • 持有對ExecutionEnvironment或StreamExecutionEnvironment的引用

二10、Flink SQL的實現原理是什麼? 是如何實現 SQL 解析的呢?

首先你們要知道 Flink 的SQL解析是基於Apache Calcite這個開源框架。
file

基於此,一次完整的SQL解析過程以下:

  • 用戶使用對外提供Stream SQL的語法開發業務應用
  • 用calcite對StreamSQL進行語法檢驗,語法檢驗經過後,轉換成calcite的邏輯樹節點;最終造成calcite的邏輯計劃
  • 採用Flink自定義的優化規則和calcite火山模型、啓發式模型共同對邏輯樹進行優化,生成最優的Flink物理計劃
  • 對物理計劃採用janino codegen生成代碼,生成用低階API DataStream 描述的流應用,提交到Flink平臺執行

第二部分:Flink 面試進階篇

1、Flink是如何支持批流一體的?

file

本道面試題考察的其實就是一句話:Flink的開發者認爲批處理是流處理的一種特殊狀況。批處理是有限的流處理。Flink 使用一個引擎支持了DataSet API 和 DataStream API。

2、Flink是如何作到高效的數據交換的?

在一個Flink Job中,數據須要在不一樣的task中進行交換,整個數據交換是有 TaskManager 負責的,TaskManager 的網絡組件首先從緩衝buffer中收集records,而後再發送。Records 並非一個一個被髮送的,二是積累一個批次再發送,batch 技術能夠更加高效的利用網絡資源。

3、Flink是如何作容錯的?

Flink 實現容錯主要靠強大的CheckPoint機制和State機制。Checkpoint 負責定時製做分佈式快照、對程序中的狀態進行備份;State 用來存儲計算過程當中的中間狀態。

4、Flink 分佈式快照的原理是什麼?

Flink的分佈式快照是根據Chandy-Lamport算法量身定作的。簡單來講就是持續建立分佈式數據流及其狀態的一致快照。

file

核心思想是在 input source 端插入 barrier,控制 barrier 的同步來實現 snapshot 的備份和 exactly-once 語義。

5、Flink 是如何保證Exactly-once語義的?

Flink經過實現兩階段提交和狀態保存來實現端到端的一致性語義。
分爲如下幾個步驟:

  • 開始事務(beginTransaction)建立一個臨時文件夾,來寫把數據寫入到這個文件夾裏面
  • 預提交(preCommit)將內存中緩存的數據寫入文件並關閉
  • 正式提交(commit)將以前寫完的臨時文件放入目標目錄下。這表明着最終的數據會有一些延遲
  • 丟棄(abort)丟棄臨時文件

若失敗發生在預提交成功後,正式提交前。能夠根據狀態來提交預提交的數據,也可刪除預提交的數據。

6、Flink 的 kafka 鏈接器有什麼特別的地方?

Flink源碼中有一個獨立的connector模塊,全部的其餘connector都依賴於此模塊,Flink 在1.9版本發佈的全新kafka鏈接器,摒棄了以前鏈接不一樣版本的kafka集羣須要依賴不一樣版本的connector這種作法,只須要依賴一個connector便可。

7、說說 Flink的內存管理是如何作的?

Flink 並非將大量對象存在堆上,而是將對象都序列化到一個預分配的內存塊上。此外,Flink大量的使用了堆外內存。若是須要處理的數據超出了內存限制,則會將部分數據存儲到硬盤上。
Flink 爲了直接操做二進制數據實現了本身的序列化框架。

理論上Flink的內存管理分爲三部分:

  • Network Buffers:這個是在TaskManager啓動的時候分配的,這是一組用於緩存網絡數據的內存,每一個塊是32K,默認分配2048個,能夠經過「taskmanager.network.numberOfBuffers」修改
  • Memory Manage pool:大量的Memory Segment塊,用於運行時的算法(Sort/Join/Shuffle等),這部分啓動的時候就會分配。下面這段代碼,根據配置文件中的各類參數來計算內存的分配方法。(heap or off-heap,這個放到下節談),內存的分配支持預分配和lazy load,默認懶加載的方式。
  • User Code,這部分是除了Memory Manager以外的內存用於User code和TaskManager自己的數據結構。

8、說說 Flink的序列化如何作的?

Java自己自帶的序列化和反序列化的功能,可是輔助信息佔用空間比較大,在序列化對象時記錄了過多的類信息。

Apache Flink摒棄了Java原生的序列化方法,以獨特的方式處理數據類型和序列化,包含本身的類型描述符,泛型類型提取和類型序列化框架。

TypeInformation 是全部類型描述符的基類。它揭示了該類型的一些基本屬性,而且能夠生成序列化器。TypeInformation 支持如下幾種類型:

  • BasicTypeInfo: 任意Java 基本類型或 String 類型
  • BasicArrayTypeInfo: 任意Java基本類型數組或 String 數組
  • WritableTypeInfo: 任意 Hadoop Writable 接口的實現類
  • TupleTypeInfo: 任意的 Flink Tuple 類型(支持Tuple1 to Tuple25)。Flink tuples 是固定長度固定類型的Java Tuple實現
  • CaseClassTypeInfo: 任意的 Scala CaseClass(包括 Scala tuples)
  • PojoTypeInfo: 任意的 POJO (Java or Scala),例如,Java對象的全部成員變量,要麼是 public 修飾符定義,要麼有 getter/setter 方法
  • GenericTypeInfo: 任意沒法匹配以前幾種類型的類

針對前六種類型數據集,Flink皆能夠自動生成對應的TypeSerializer,能很是高效地對數據集進行序列化和反序列化。

9、 Flink中的Window出現了數據傾斜,你有什麼解決辦法?

window產生數據傾斜指的是數據在不一樣的窗口內堆積的數據量相差過多。本質上產生這種狀況的緣由是數據源頭髮送的數據量速度不一樣致使的。出現這種狀況通常經過兩種方式來解決:

  • 在數據進入窗口前作預聚合
  • 從新設計窗口聚合的key

10、 Flink中在使用聚合函數 GroupBy、Distinct、KeyBy 等函數時出現數據熱點該如何解決?

數據傾斜和數據熱點是全部大數據框架繞不過去的問題。處理這類問題主要從3個方面入手:

  • 在業務上規避這類問題

例如一個假設訂單場景,北京和上海兩個城市訂單量增加幾十倍,其他城市的數據量不變。這時候咱們在進行聚合的時候,北京和上海就會出現數據堆積,咱們能夠單獨數據北京和上海的數據。

  • Key的設計上

把熱key進行拆分,好比上個例子中的北京和上海,能夠把北京和上海按照地區進行拆分聚合。

  • 參數設置

Flink 1.9.0 SQL(Blink Planner) 性能優化中一項重要的改進就是升級了微批模型,即 MiniBatch。原理是緩存必定的數據後再觸發處理,以減小對State的訪問,從而提高吞吐和減小數據的輸出量。

11、Flink任務延遲高,想解決這個問題,你會如何入手?

在Flink的後臺任務管理中,咱們能夠看到Flink的哪一個算子和task出現了反壓。最主要的手段是資源調優和算子調優。資源調優便是對做業中的Operator的併發數(parallelism)、CPU(core)、堆內存(heap_memory)等參數進行調優。做業參數調優包括:並行度的設置,State的設置,checkpoint的設置。

12、Flink是如何處理反壓的?

Flink 內部是基於 producer-consumer 模型來進行消息傳遞的,Flink的反壓設計也是基於這個模型。Flink 使用了高效有界的分佈式阻塞隊列,就像 Java 通用的阻塞隊列(BlockingQueue)同樣。下游消費者消費變慢,上游就會受到阻塞。

十3、Flink的反壓和Strom有哪些不一樣?

Storm 是經過監控 Bolt 中的接收隊列負載狀況,若是超太高水位值就會將反壓信息寫到 Zookeeper ,Zookeeper 上的 watch 會通知該拓撲的全部 Worker 都進入反壓狀態,最後 Spout 中止發送 tuple。

Flink中的反壓使用了高效有界的分佈式阻塞隊列,下游消費變慢會致使發送端阻塞。

兩者最大的區別是Flink是逐級反壓,而Storm是直接從源頭降速。

十4、 Operator Chains(算子鏈)這個概念你瞭解嗎?

爲了更高效地分佈式執行,Flink會盡量地將operator的subtask連接(chain)在一塊兒造成task。每一個task在一個線程中執行。將operators連接成task是很是有效的優化:它能減小線程之間的切換,減小消息的序列化/反序列化,減小數據在緩衝區的交換,減小了延遲的同時提升總體的吞吐量。這就是咱們所說的算子鏈。

十5、 Flink什麼狀況下才會把Operator chain在一塊兒造成算子鏈?

兩個operator chain在一塊兒的的條件:

  • 上下游的並行度一致
  • 下游節點的入度爲1 (也就是說下游節點沒有來自其餘節點的輸入)
  • 上下游節點都在同一個 slot group 中(下面會解釋 slot group)
  • 下游節點的 chain 策略爲 ALWAYS(能夠與上下游連接,map、flatmap、filter等默認是ALWAYS)
  • 上游節點的 chain 策略爲 ALWAYS 或 HEAD(只能與下游連接,不能與上游連接,Source默認是HEAD)
  • 兩個節點間數據分區方式是 forward(參考理解數據流的分區)
  • 用戶沒有禁用 chain

十6、 說說Flink1.9的新特性?

  • 支持hive讀寫,支持UDF
  • Flink SQL TopN和GroupBy等優化
  • Checkpoint跟savepoint針對實際業務場景作了優化
  • Flink state查詢

十7、消費kafka數據的時候,如何處理髒數據?

能夠在處理前加一個fliter算子,將不符合規則的數據過濾出去。

第三部分:Flink 面試源碼篇

1、Flink Job的提交流程
用戶提交的Flink Job會被轉化成一個DAG任務運行,分別是:StreamGraph、JobGraph、ExecutionGraph,Flink中JobManager與TaskManager,JobManager與Client的交互是基於Akka工具包的,是經過消息驅動。整個Flink Job的提交還包含着ActorSystem的建立,JobManager的啓動,TaskManager的啓動和註冊。

2、Flink所謂"三層圖"結構是哪幾個"圖"?

一個Flink任務的DAG生成計算圖大體經歷如下三個過程:

  • StreamGraph
    最接近代碼所表達的邏輯層面的計算拓撲結構,按照用戶代碼的執行順序向StreamExecutionEnvironment添加StreamTransformation構成流式圖。
  • JobGraph
    從StreamGraph生成,將能夠串聯合並的節點進行合併,設置節點之間的邊,安排資源共享slot槽位和放置相關聯的節點,上傳任務所需的文件,設置檢查點配置等。至關於通過部分初始化和優化處理的任務圖。
  • ExecutionGraph
    由JobGraph轉換而來,包含了任務具體執行所需的內容,是最貼近底層實現的執行圖。

3、JobManger在集羣中扮演了什麼角色?

JobManager 負責整個 Flink 集羣任務的調度以及資源的管理,從客戶端中獲取提交的應用,而後根據集羣中 TaskManager 上 TaskSlot 的使用狀況,爲提交的應用分配相應的 TaskSlot 資源並命令 TaskManager 啓動從客戶端中獲取的應用。

JobManager 至關於整個集羣的 Master 節點,且整個集羣有且只有一個活躍的 JobManager ,負責整個集羣的任務管理和資源管理。

JobManager 和 TaskManager 之間經過 Actor System 進行通訊,獲取任務執行的狀況並經過 Actor System 將應用的任務執行狀況發送給客戶端。

同時在任務執行的過程當中,Flink JobManager 會觸發 Checkpoint 操做,每一個 TaskManager 節點 收到 Checkpoint 觸發指令後,完成 Checkpoint 操做,全部的 Checkpoint 協調過程都是在 Fink JobManager 中完成。

當任務完成後,Flink 會將任務執行的信息反饋給客戶端,而且釋放掉 TaskManager 中的資源以供下一次提交任務使用。

4、JobManger在集羣啓動過程當中起到什麼做用?

JobManager的職責主要是接收Flink做業,調度Task,收集做業狀態和管理TaskManager。它包含一個Actor,而且作以下操做:

  • RegisterTaskManager: 它由想要註冊到JobManager的TaskManager發送。註冊成功會經過AcknowledgeRegistration消息進行Ack。
  • SubmitJob: 由提交做業到系統的Client發送。提交的信息是JobGraph形式的做業描述信息。
  • CancelJob: 請求取消指定id的做業。成功會返回CancellationSuccess,不然返回CancellationFailure。
  • UpdateTaskExecutionState: 由TaskManager發送,用來更新執行節點(ExecutionVertex)的狀態。成功則返回true,不然返回false。
  • RequestNextInputSplit: TaskManager上的Task請求下一個輸入split,成功則返回NextInputSplit,不然返回null。
  • JobStatusChanged: 它意味着做業的狀態(RUNNING, CANCELING, FINISHED,等)發生變化。這個消息由ExecutionGraph發送。

5、TaskManager在集羣中扮演了什麼角色?

TaskManager 至關於整個集羣的 Slave 節點,負責具體的任務執行和對應任務在每一個節點上的資源申請和管理。

客戶端經過將編寫好的 Flink 應用編譯打包,提交到 JobManager,而後 JobManager 會根據已註冊在 JobManager 中 TaskManager 的資源狀況,將任務分配給有資源的 TaskManager節點,而後啓動並運行任務。

TaskManager 從 JobManager 接收須要部署的任務,而後使用 Slot 資源啓動 Task,創建數據接入的網絡鏈接,接收數據並開始數據處理。同時 TaskManager 之間的數據交互都是經過數據流的方式進行的。

能夠看出,Flink 的任務運行實際上是採用多線程的方式,這和 MapReduce 多 JVM 進行的方式有很大的區別,Flink 可以極大提升 CPU 使用效率,在多個任務和 Task 之間經過 TaskSlot 方式共享系統資源,每一個 TaskManager 中經過管理多個 TaskSlot 資源池進行對資源進行有效管理。

6、TaskManager在集羣啓動過程當中起到什麼做用?

TaskManager的啓動流程較爲簡單:
啓動類:org.apache.flink.runtime.taskmanager.TaskManager
核心啓動方法 : selectNetworkInterfaceAndRunTaskManager
啓動後直接向JobManager註冊本身,註冊完成後,進行部分模塊的初始化。

7、Flink 計算資源的調度是如何實現的?

TaskManager中最細粒度的資源是Task slot,表明了一個固定大小的資源子集,每一個TaskManager會將其所佔有的資源平分給它的slot。

經過調整 task slot 的數量,用戶能夠定義task之間是如何相互隔離的。每一個 TaskManager 有一個slot,也就意味着每一個task運行在獨立的 JVM 中。每一個 TaskManager 有多個slot的話,也就是說多個task運行在同一個JVM中。

而在同一個JVM進程中的task,能夠共享TCP鏈接(基於多路複用)和心跳消息,能夠減小數據的網絡傳輸,也能共享一些數據結構,必定程度上減小了每一個task的消耗。
每一個slot能夠接受單個task,也能夠接受多個連續task組成的pipeline,以下圖所示,FlatMap函數佔用一個taskslot,而key Agg函數和sink函數共用一個taskslot:
file

8、簡述Flink的數據抽象及數據交換過程?

Flink 爲了不JVM的固有缺陷例如java對象存儲密度低,FGC影響吞吐和響應等,實現了自主管理內存。MemorySegment就是Flink的內存抽象。默認狀況下,一個MemorySegment能夠被看作是一個32kb大的內存塊的抽象。這塊內存既能夠是JVM裏的一個byte[],也能夠是堆外內存(DirectByteBuffer)。

在MemorySegment這個抽象之上,Flink在數據從operator內的數據對象在向TaskManager上轉移,預備被髮給下個節點的過程當中,使用的抽象或者說內存對象是Buffer。

對接從Java對象轉爲Buffer的中間對象是另外一個抽象StreamRecord。

9、Flink 中的分佈式快照機制是如何實現的?

Flink的容錯機制的核心部分是製做分佈式數據流和操做算子狀態的一致性快照。 這些快照充當一致性checkpoint,系統能夠在發生故障時回滾。 Flink用於製做這些快照的機制在「分佈式數據流的輕量級異步快照」中進行了描述。 它受到分佈式快照的標準Chandy-Lamport算法的啓發,專門針對Flink的執行模型而定製。

file

barriers在數據流源處被注入並行數據流中。快照n的barriers被插入的位置(咱們稱之爲Sn)是快照所包含的數據在數據源中最大位置。例如,在Apache Kafka中,此位置將是分區中最後一條記錄的偏移量。 將該位置Sn報告給checkpoint協調器(Flink的JobManager)。

而後barriers向下遊流動。當一箇中間操做算子從其全部輸入流中收到快照n的barriers時,它會爲快照n發出barriers進入其全部輸出流中。 一旦sink操做算子(流式DAG的末端)從其全部輸入流接收到barriers n,它就向checkpoint協調器確認快照n完成。在全部sink確認快照後,意味快照着已完成。

一旦完成快照n,job將永遠再也不向數據源請求Sn以前的記錄,由於此時這些記錄(及其後續記錄)將已經經過整個數據流拓撲,也便是已經被處理結束。

10、簡單說說FlinkSQL的是如何實現的?

Flink 將 SQL 校驗、SQL 解析以及 SQL 優化交給了Apache Calcite。Calcite 在其餘不少開源項目裏也都應用到了,譬如 Apache Hive, Apache Drill, Apache Kylin, Cascading。Calcite 在新的架構中處於核心的地位,以下圖所示。
file

構建抽象語法樹的事情交給了 Calcite 去作。SQL query 會通過 Calcite 解析器轉變成 SQL 節點樹,經過驗證後構建成 Calcite 的抽象語法樹(也就是圖中的 Logical Plan)。另外一邊,Table API 上的調用會構建成 Table API 的抽象語法樹,並經過 Calcite 提供的 RelBuilder 轉變成 Calcite 的抽象語法樹。而後依次被轉換成邏輯執行計劃和物理執行計劃。

在提交任務後會分發到各個 TaskManager 中運行,在運行時會使用 Janino 編譯器編譯代碼後運行。

歡迎關注做者其餘 Chat:

大數據開發面試指南 Flink 最鋒利的武器:Flink SQL 入門和實戰

大數據開發面試指南

實時數倉 | 你須要的是一款強大的 OLAP 引擎

聲明:本號全部文章除特殊註明,都爲原創,公衆號讀者擁有優先閱讀權,未經做者本人容許不得轉載,不然追究侵權責任。

關注個人公衆號,後臺回覆【JAVAPDF】獲取200頁面試題!
5萬人關注的大數據成神之路,不來了解一下嗎?
5萬人關注的大數據成神之路,真的不來了解一下嗎?
5萬人關注的大數據成神之路,肯定真的不來了解一下嗎?

歡迎您關注《大數據成神之路》

大數據技術與架構

相關文章
相關標籤/搜索