Flink【優質】面試

一、概念和基礎篇
1. 簡單介紹一下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有什麼區別?
這個問題問的很大,分幾個方面回答:

架構模型上:Spark Streaming 的task運行依賴driver 和 executor和worker,當然driver和excutor還依賴於集羣管理器Standalone或者yarn等。而Flink運行時主要是JobManager、TaskManage和TaskSlot。另外一個最核心的區別是:Spark Streaming 是微批處理,運行的時候需要指定批處理的時間,每次運行 job 時處理一個批次的數據;Flink 是基於事件驅動的,事件可以理解爲消息。事件驅動的應用程序是一種狀態應用程序,它會從一個或者多個流中注入事件,通過觸發計算更新狀態,或外部動作對注入的事件作出反應。

任務調度上:Spark Streaming的調度分爲構建 DGA 圖,劃分 stage,生成 taskset,調度 task等步驟而Flink首先會生成 StreamGraph,接着生成 JobGraph,然後將 jobGraph 提交給 Jobmanager 由它完成 jobGraph 到 ExecutionGraph 的轉變,最後由 jobManager 調度執行。

時間機制上:flink 支持三種時間機制事件時間,注入時間,處理時間,同時支持 watermark 機制處理滯後數據。Spark Streaming 只支持處理時間,Structured streaming則支持了事件時間和watermark機制。

容錯機制上:二者保證exactly-once的方式不同。spark streaming 通過保存offset和事務的方式;Flink 則使用兩階段提交協議來解決這個問題。

3. Flink的組件棧是怎麼樣的
Flink是一個分層架構的系統,每一層所包含的組件都提供了特定的抽象,用來服務於上層組件。

Flink分層的組件棧如下圖所示:

Deployment層

該層主要涉及了Flink的部署模式,Flink支持多種部署模式:本地、集羣(Standalone/YARN)、雲(GCE/EC2)。

Runtime層

Runtime層提供了支持Flink計算的全部核心實現,比如:支持分佈式Stream處理、JobGraph到ExecutionGraph的映射、調度等等,爲上層API層提供基礎服務。

API層

API層主要實現了面向無界Stream的流處理和麪向Batch的批處理API,其中面向流處理對應DataStream API,面向批處理對應DataSet API。

Libraries層

該層也可以稱爲Flink應用框架層,根據API層的劃分,在API層之上構建的滿足特定應用的實現計算框架,也分別對應於面向流處理和麪向批處理兩類。面向流處理支持:CEP(複雜事件處理)、基於SQL-like的操作(基於Table的關係操作);面向批處理支持:FlinkML(機器學習庫)、Gelly(圖處理)。

4. Flink的基礎編程模型瞭解嗎?
Flink 程序的基礎構建單元是流(streams)與轉換(transformations)。DataSet API 中使用的數據集也是一種流。數據流(stream)就是一組永遠不會停止的數據記錄流,而轉換(transformation)是將一個或多個流作爲輸入,並生成一個或多個輸出流的操作。

執行時,Flink程序映射到 streaming dataflows,由流(streams)和轉換操作(transformation operators)組成。每個 dataflow 從一個或多個源(source)開始,在一個或多個接收器(sink)中結束。

詳細參考:https://www.cnblogs.com/cxhfuujust/p/10925843.html

5. 說說Flink架構中的角色和作用?


JobManager:

JobManager是Flink系統的協調者,它負責接收Flink Job,調度組成Job的多個Task的執行。同時,JobManager還負責收集Job的狀態信息,並管理Flink集羣中從節點TaskManager。

TaskManager:

TaskManager也是一個Actor,它是實際負責執行計算的Worker,在其上執行Flink Job的一組Task。每個TaskManager負責管理其所在節點上的資源信息,如內存、磁盤、網絡,在啓動的時候將資源的狀態向JobManager彙報。

Client:

當用戶提交一個Flink程序時,會首先創建一個Client,該Client首先會對用戶提交的Flink程序進行預處理,並提交到Flink集羣中處理,所以Client需要從用戶提交的Flink程序配置中獲取JobManager的地址,並建立到JobManager的連接,將Flink Job提交給JobManager。Client會將用戶提交的Flink程序組裝一個JobGraph, 並且是以JobGraph的形式提交的。一個JobGraph是一個Flink Dataflow,它由多個JobVertex組成的DAG。其中,一個JobGraph包含了一個Flink程序的如下信息:JobID、Job名稱、配置信息、一組JobVertex等。

6. 說說Flink中常用的算子?用過哪些?
舉一些常用的例子:

flink中提供的大量的算子,下面將介紹常用的算子操作方式:

map
DataStream --> DataStream:輸入一個參數產生一個參數,map的功能是對輸入的參數進行轉換操作。

flatMap
DataStream --> DataStream:輸入一個參數,產生0、1或者多個輸出,這個多用於拆分操作

filter
DataStream --> DataStream:結算每個元素的布爾值,並返回爲true的元素

keyBy
DataSteam --> DataStream:邏輯地將一個流拆分成不相交的分區,每個分區包含具有相同key的元素,在內部以hash的形式實現的。以key來分組。

注意:以下類型無法作爲key

POJO類,且沒有實現hashCode函數
任意形式的數組類型
reduce
KeyedStream --> DataStream:滾動合併操作,合併當前元素和上一次合併的元素結果。

fold
KeyedStream --> DataStream:用一個初始的一個值,與其每個元素進行滾動合併操作。

aggregation
KeyedStream --> DataStream:分組流數據的滾動聚合操作:min和minBy的區別是min返回的是一個最小值,而minBy返回的是其字段中包含的最小值的元素(同樣元原理適用於max和maxBy)

window
KeyedStream --> DataStream:windows是在一個分區的KeyedStreams中定義的,windows根據某些特性將每個key的數據進行分組(例如:在5s內到達的數據)。

windowAll
DataStream --> AllWindowedStream:Windows可以在一個常規的DataStream中定義,Windows根據某些特性對所有的流(例如:5s內到達的數據)。

注意:這個操作在很多情況下都不是並行操作的,所有的記錄都會聚集到一個windowAll操作的任務中

window apply
WindowedStream --> DataStream

AllWindowedStream --> DataStream:將一個通用的函數作爲一個整體傳遞給window。

window reduce
WindowedStream --> DataStream:給窗口賦予一個reduce的功能,並返回一個reduce的結果。

window fold
WindowedStream --> DataStream:給窗口賦予一個fold的功能,並返回一個fold後的結果。

aggregation on windows
WindowedStream --> DataStream:對window的元素做聚合操作,min和minBy的區別是min返回的是最小值,而minBy返回的是包含最小值字段的元素。(同樣原理適用於max和maxBy)

union
DataStream --> DataStream:對兩個或兩個以上的DataStream做union操作,產生一個包含所有的DataStream元素的新DataStream。

注意:如果將一個DataStream和自己做union操作,在新的DataStream中,將看到每個元素重複兩次

window join
DataStream,DataStream --> DataStream:根據給定的key和window對兩個DataStream做join操作

window coGroup
DataStream,DataStream --> DataStream:根據一個給定的key和window對兩個DataStream做CoGroups操作。

connect
DataStream,DataStream --> ConnectedStreams:連接兩個保持它們類型的數據流。

coMap、coFlatMap
ConnectedStreams --> DataStream:作用於connected數據流上,功能與map和flatMap一樣。

split

DataStream --> SplitStream:根據某些特徵把一個DataStream拆分成兩個或多個DataStream

select
SplitStream --> DataStream:從一個SplitStream中獲取一個或多個DataStream

iterate
DataStream --> IterativeStream --> DataStream:在流程中創建一個反饋循環,將一個操作的輸出重定向到之前的操作,這對於定義持續更新模型的算法來說很有意義的。

extract timestamps

DataStream --> DataStream:提取記錄中的時間戳來跟需要事件時間的window一起發揮作用。

參考:https://ci.apache.org/projects/flink/flink-docs-release-1.9/dev/batch/

7. Flink中的分區策略有哪幾種?
GlobalPartitioner: DataStream => DataStream
GlobalPartitioner,GLOBAL分區。將記錄輸出到下游Operator的第一個實例。

ShufflePartitioner: DataStream => DataStream
ShufflePartitioner,SHUFFLE分區。將記錄隨機輸出到下游Operator的每個實例。

RebalancePartitioner: DataStream => DataStream
RebalancePartitioner,REBALANCE分區。將記錄以循環的方式輸出到下游Operator的每個實例。

RescalePartitioner: DataStream => DataStream
RescalePartitioner,RESCALE分區。基於上下游Operator的並行度,將記錄以循環的方式輸出到下游Operator的每個實例。舉例: 上游並行度是2,下游是4,則上游一個並行度以循環的方式將記錄輸出到下游的兩個並行度上;上游另一個並行度以循環的方式將記錄輸出到下游另兩個並行度上。若上游並行度是4,下游並行度是2,則上游兩個並行度將記錄輸出到下游一個並行度上;上游另兩個並行度將記錄輸出到下游另一個並行度上。

BroadcastPartitioner: DataStream => DataStream
BroadcastPartitioner,BROADCAST分區。廣播分區將上游數據集輸出到下游Operator的每個實例中。適合於大數據集Join小數據集的場景。

ForwardPartitioner
ForwardPartitioner,FORWARD分區。將記錄輸出到下游本地的operator實例。ForwardPartitioner分區器要求上下游算子並行度一樣。上下游Operator同屬一個SubTasks。

KeyGroupStreamPartitioner(HASH方式):
KeyGroupStreamPartitioner,HASH分區。將記錄按Key的Hash值輸出到下游Operator實例。

CustomPartitionerWrapper
CustomPartitionerWrapper,CUSTOM分區。通過Partitioner實例的partition方法(自定義的)將記錄輸出到下游。

8. Flink的並行度有了解嗎?Flink中設置並行度需要注意什麼?
Flink程序由多個任務(Source、Transformation、Sink)組成。任務被分成多個並行實例來執行,每個並行實例處理任務的輸入數據的子集。任務的並行實例的數量稱之爲並行度。

Flink中任務的並行度可以從多個不同層面設置:

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

Flink可以設置好幾個level的parallelism,其中包括Operator Level、Execution Environment Level、Client Level、System Level

在flink-conf.yaml中通過parallelism.default配置項給所有execution environments指定系統級的默認parallelism;

在ExecutionEnvironment裏頭可以通過setParallelism來給operators、data sources、data sinks設置默認的parallelism;

如果operators、data sources、data sinks自己有設置parallelism則會覆蓋ExecutionEnvironment設置的parallelism。

9. Flink支持哪幾種重啓策略?分別如何配置?
重啓策略種類:

1)固定延遲重啓策略(Fixed Delay Restart Strategy)

2)故障率重啓策略(Failure Rate Restart Strategy)

3)無重啓策略(No Restart Strategy)

4)Fallback重啓策略(Fallback Restart Strategy)

說明:

默認重啓策略是通過Flink的配置文件設置的flink-conf.yaml。定義策略的配置key爲: restart-strategy。
如果未啓用檢查點,則使用“無重啓”策略。
如果激活了檢查點但未配置重啓策略,則使用“固定延遲策略”:restart-strategy.fixed-delay.attempts: Integer.MAX_VALUE嘗試重啓。

詳細參考:https://www.jianshu.com/p/22409ccc7905

10. Flink的分佈式緩存有什麼作用?如何使用?
Flink提供了一個分佈式緩存,類似於hadoop,可以使用戶在並行函數中很方便的讀取本地文件,並把它放在taskmanager節點中,防止task重複拉取。

此緩存的工作機制如下:程序註冊一個文件或者目錄(本地或者遠程文件系統,例如hdfs或者s3),通過ExecutionEnvironment註冊緩存文件併爲它起一個名稱。

當程序執行,Flink自動將文件或者目錄複製到所有taskmanager節點的本地文件系統,僅會執行一次。用戶可以通過這個指定的名稱查找文件或者目錄,然後從taskmanager節點的本地文件系統訪問它。

詳細參考:https://www.jianshu.com/p/7770f9aec75d

11. Flink中的廣播變量,使用廣播變量需要注意什麼事項?
在Flink中,同一個算子可能存在若干個不同的並行實例,計算過程可能不在同一個Slot中進行,不同算子之間更是如此,因此不同算子的計算數據之間不能像Java數組之間一樣互相訪問,而廣播變量Broadcast便是解決這種情況的。

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

https://www.jianshu.com/p/3b6698ec10d8

12. Flink中對窗口的支持包括哪幾種?說說他們的使用場景


翻滾窗口(Tumbling Window,無重疊)
滾動窗口(Sliding Window,有重疊)
會話窗口(Session Window,活動間隙)
【補充】
Flink 提出了三種時間的概念:

 event time(事件時間:事件發生時的時間);

ingestion time(攝取時間:事件進入流處理系統的時間);

processing time(處理時間:消息被計算處理的時間)。

// **  Flink 中窗口機制和時間類型是完全解耦的,也就是說當需要改變時間類型時不需要更改窗口邏輯相關的代碼。

13. Flink 中的 State Backends是什麼?有什麼作用?分成哪幾類?說說他們各自的優缺點?
Flink流計算中可能有各種方式來保存狀態:

窗口操作
使用了KV操作的函數
繼承了CheckpointedFunction的函數
當開始做checkpointing的時候,狀態會被持久化到checkpoints裏來規避數據丟失和狀態恢復。選擇的狀態存儲策略不同,會導致狀態持久化如何和checkpoints交互。
 

Flink提供了三種持久化策略,如果沒有顯式指定,則默認使用MemoryState

Backend

MemoryStateBackend  |  數據保存在java的堆裏=
FsStateBackend   |  通過文件系統URL設置=保持數據在TM的內存中
RocksDBStateBackend  |  通過文件系統URL設置=保存數據至RocksDB
詳細參考:https://www.cnblogs.com/029zz010buct/p/9403283.html

14. Flink中的時間種類有哪些?各自介紹一下?
Flink中的時間與現實世界中的時間是不一致的,在flink中被劃分爲事件時間,攝入時間,處理時間三種。

如果以EventTime爲基準來定義時間窗口將形成EventTimeWindow,要求消息本身就應該攜帶EventTime

如果以IngesingtTime爲基準來定義時間窗口將形成IngestingTimeWindow,以source的systemTime爲準。

如果以ProcessingTime基準來定義時間窗口將形成ProcessingTimeWindow,以operator的systemTime爲準。

參考:https://www.jianshu.com/p/0a135391ff41

15. WaterMark是什麼?是用來解決什麼問題?如何生成水印?水印的原理是什麼?
Watermark是Apache Flink爲了處理EventTime 窗口計算提出的一種機制,本質上也是一種時間戳。

watermark是用於處理亂序事件的,處理亂序事件通常用watermark機制結合window來實現。

詳細參考:

https://www.jianshu.com/p/cff8cbb7408b

https://www.jianshu.com/p/2e87abfe89ff

https://www.jianshu.com/p/7d524ef8143c

16. Flink的table和SQL熟悉嗎?Table API和SQL中TableEnvironment這個類有什麼作用?
TableEnvironment是Table API和SQL集成的核心概念。它負責:

  A)在內部catalog中註冊表

  B)註冊外部catalog

  C)執行SQL查詢

  D)註冊用戶定義(標量,表或聚合)函數

  E)將DataStream或DataSet轉換爲表

  F)持有對ExecutionEnvironment或StreamExecutionEnvironment的引用

17. Flink如何實現SQL解析的呢?


StreamSQL API的執行原理如下:

1、用戶使用對外提供Stream SQL的語法開發業務應用;

2、用calcite對StreamSQL進行語法檢驗,語法檢驗通過後,轉換成calcite的邏輯樹節點;最終形成calcite的邏輯計劃;

3、採用Flink自定義的優化規則和calcite火山模型、啓發式模型共同對邏輯樹進行優化,生成最優的Flink物理計劃;

4、對物理計劃採用janino codegen生成代碼,生成用低階API DataStream 描述的流應用,提交到Flink平臺執行

詳細參考:https://cloud.tencent.com/developer/article/1471612

二、進階篇
1. Flink是如何做到批處理與流處理統一的?
Flink設計者認爲:有限流處理是無限流處理的一種特殊情況,它只不過在某個時間點停止而已。Flink通過一個底層引擎同時支持流處理和批處理。

 

批處理是流處理的一種非常特殊的情況。在流處理中,我們爲數據定義滑 動窗口或滾動窗口,並且在每次窗口滑動或滾動時生成結果。批處理則不同,我們定義一個全局窗口,所有的記錄都屬於同一個窗口。

詳細參考:https://cloud.tencent.com/developer/article/1501348

2. Flink中的數據傳輸模式是怎麼樣的?
在一個運行的application中,它的tasks在持續交換數據。TaskManager負責做數據傳輸。

TaskManager的網絡組件首先從緩衝buffer中收集records,然後再發送。也就是說,records並不是一個接一個的發送,而是先放入緩衝,然後再以batch的形式發送。這個技術可以高效使用網絡資源,並達到高吞吐。類似於網絡或磁盤 I/O 協議中使用的緩衝技術。

詳細參考:https://www.cnblogs.com/029zz010buct/p/10156836.html

3. Flink的容錯機制
Flink基於分佈式快照與可部分重發的數據源實現了容錯。用戶可自定義對整個Job進行快照的時間間隔,當任務失敗時,Flink會將整個Job恢復到最近一次快照,並從數據源重發快照之後的數據。

詳細參考:https://www.jianshu.com/p/1fca8fb61f86

4. Flink中的分佈式快照機制是怎麼樣的
Flink容錯機制的核心就是持續創建分佈式數據流及其狀態的一致快照。這些快照在系統遇到故障時,充當可以回退的一致性檢查點(checkpoint)。Lightweight Asynchronous Snapshots for Distributed Dataflows 描述了Flink創建快照的機制。此論文是受分佈式快照算法 Chandy-Lamport啓發,並針對Flink執行模型量身定製。

可以參考:

https://zhuanlan.zhihu.com/p/43536305

https://blog.csdn.net/u014589856/article/details/94346801

5. Flink是如何實現Exactly-once的?
exactly-once語義就是保證最後的數據處理的結果和數據攝入時沒有數據的丟失與重複。

【Checkpoint】

checkpoint包含了,flink應用現在的狀態與數據輸入流的位置(對於kafka來說就是offset);
checkpoint可異步的持久化到像s3或者hdfs這樣子的存儲系統裏面。如果flink應用失敗或者升級時,可以拉取checkpoint中的狀態來恢復上次失敗時的數據。
在flink1.4.0之前,flink通過checkpoint保證了flink應用內部的exactly-once語義。現在加入了TwoPhaseCommitSinkFunctio可以保證端到端的exactly-once語義。
兩次提交來保證語義的方式需要flink所連接的外部系統支持兩部提交,也就是外部系統要支持可以預提交和回滾沒有最終提交的數據這樣子的特性。

 

Flink通過狀態和兩次提交協議來保證了端到端的exactly-once語義。

兩步提交的類有四個狀態:

開始事物(beginTransaction)- 創建一個臨時文件夾,來寫把數據寫入到這個文件夾裏面。
預提交(preCommit)- 將內存中緩存的數據寫入文件並關閉。
正式提交(commit)- 將之前寫完的臨時文件放入目標目錄下。這代表着最終的數據會有一些延遲。
丟棄(abort)- 丟棄臨時文件
若失敗發生在預提交成功後,正式提交前。可以根據狀態來提交預提交的數據,也可刪除預提交的數據。

詳細請看:https://www.jianshu.com/p/9d875f6e54f2

6. Flink的Kafka-connector是如何做到向下兼容的呢?
在新的連接器中,Flink提供了一個基礎connector模塊,它是實現所有connector的核心模塊,所有的connector都依賴於基礎connector。

Kafka社區也改寫了Java clients底層的網絡客戶端代碼,裏面會自動地判斷連接的broker端所支持client請求的最高版本,並自動創建合乎標準的請求。

詳細參考:

https://www.cnblogs.com/Springmoon-venn/p/10690531.html

https://www.cnblogs.com/huxi2b/p/6784795.html

關於flink-kafka-connector的實現參考:

https://www.cnblogs.com/0x12345678/p/10463539.html

7. Flink中的內存管理是如何做的?
Flink 並不是將大量對象存在堆上,而是將對象都序列化到一個預分配的內存塊上,這個內存塊叫做 MemorySegment,它代表了一段固定長度的內存(默認大小爲 32KB),也是 Flink 中最小的內存分配單元,並且提供了非常高效的讀寫方法。每條記錄都會以序列化的形式存儲在一個或多個MemorySegment中。

Flink堆內存劃分:

Network Buffers: 一定數量的32KB大小的緩存,主要用於數據的網絡傳輸。在 TaskManager啓動的時候就會分配。默認數量是2048個,可以通過 taskmanager.network.numberOfBuffers來配置。

Memory Manager Pool:這是一個由MemoryManager管理的,由衆多MemorySegment組成的超大集合。Flink中的算法(如 sort/shuffle/join)會向這個內存池申請MemorySegment,將序列化後的數據存於其中,使用完後釋放回內存池。默認情況下,池子佔了堆內存的70% 的大小。

Remaining (Free) Heap: 這部分的內存是留給用戶代碼以及TaskManager 的數據結構使用的,可以把這裏看成的新生代。

Flink大量使用堆外內存。

詳細參考:

https://www.cnblogs.com/ooffff/p/9508271.html

8. Flink中的序列化是如何做的?
Flink實現了自己的序列化框架,Flink處理的數據流通常是一種類型,所以可以只保存一份對象Schema信息,節省存儲空間。又因爲對象類型固定,所以可以通過偏移量存取。

Java支持任意Java或Scala類型,類型信息由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,能非常高效地對數據集進行序列化和反序列化。對於最後一種數據類型,Flink會使用Kryo進行序列化和反序列化。每個TypeInformation中,都包含了serializer,類型會自動通過serializer進行序列化,然後用Java Unsafe接口寫入MemorySegments。如下圖展示 一個內嵌型的Tuple3<integer,double,person> 對象的序列化過程:

操縱二進制數據:

Flink提供瞭如group、sort、join等操作,這些操作都需要訪問海量數據。以sort爲例:首先,Flink會從MemoryManager中申請一批 MemorySegment,用來存放排序的數據。

這些內存會分爲兩部分,一個區域是用來存放所有對象完整的二進制數據。另一個區域用來存放指向完整二進制數據的指針以及定長的序列化後的key(key+pointer)。將實際的數據和point+key分開存放有兩個目的。

第一,交換定長塊(key+pointer)更高效,不用交換真實的數據也不用移動其他key和pointer;

第二,這樣做是緩存友好的,因爲key都是連續存儲在內存中的,可以增加cache命中。排序會先比較 key 大小,這樣就可以直接用二進制的 key 比較而不需要反序列化出整個對象。訪問排序後的數據,可以沿着排好序的key+pointer順序訪問,通過 pointer 找到對應的真實數據。

詳細參考:https://www.cnblogs.com/ooffff/p/9508271.html

9.Flink中的RPC框架選型是怎麼樣的?
對於Flink中各個組件(JobMaster、TaskManager、Dispatcher等),其底層RPC框架基於Akka實現。如果你對akka不瞭解,那麼參考:https://www.cnblogs.com/letsfly/p/10853341.html

https://www.jianshu.com/p/7d941a3b0ccb

10. Flink在使用Window時出現數據傾斜,你有什麼解決辦法?
注意:這裏window產生的數據傾斜指的是不同的窗口內積攢的數據量不同,主要是由源頭數據的產生速度導致的差異。

核心思路:1.重新設計key 2.在窗口計算前做預聚合

可以參考這個:

https://blog.csdn.net/it_lee_j_h/article/details/88641894

11. Flink SQL在使用Groupby時出現熱點數據,如何處理?
對於開源的Flink,可以參考:https://help.aliyun.com/knowledge_detail/68645.html

12. Flink任務,delay極高,請問你有什麼調優策略?
首先要確定問題產生的原因,找到最耗時的點,確定性能瓶頸點。比如任務頻繁反壓,找到反壓點。主要通過:資源調優、作業參數調優。資源調優即是對作業中的Operator的併發數(parallelism)、CPU(core)、堆內存(heap_memory)等參數進行調優。作業參數調優包括:並行度的設置,State的設置,checkpoint的設置。

13. Flink是如何處理反壓backpressure的?和Spark有什麼區別?Storm呢?
Storm 是通過監控 Bolt 中的接收隊列負載情況,如果超過高水位值就會將反壓信息寫到 Zookeeper ,Zookeeper 上的 watch 會通知該拓撲的所有 Worker 都進入反壓狀態,最後 Spout 停止發送 tuple。具體實現可以看這個 JIRA STORM-886。

 

(JStorm 認爲直接停止 Spout 的發送太過暴力,存在大量問題。當下游出現阻塞時,上游停止發送,下游消除阻塞後,上游又開閘放水,過了一會兒,下游又阻塞,上游又限流,如此反覆,整個數據流會一直處在一個顛簸狀態。所以 JStorm 是通過逐級降速來進行反壓的,效果會較 Storm 更爲穩定,但算法也更復雜。另外 JStorm 沒有引入 Zookeeper 而是通過 TopologyMaster 來協調拓撲進入反壓狀態,這降低了 Zookeeper 的負載。)

 

Flink利用自身作爲純數據流引擎的優勢來優雅地響應反壓問題。

當輸出緩衝中的字節數超過了高水位值, 則 Channel.isWritable() 會返回false。當輸出緩存中的字節數又掉到了低水位值以下, 則 Channel.isWritable() 會重新返回true。Flink 中發送數據的核心代碼在 PartitionRequestQueue 中,該類是 server channel pipeline 的最後一層。

參考:https://yq.aliyun.com/articles/64821

14. Operator Chains(算子鏈)這個概念你瞭解嗎?Flink是如何優化的?什麼情況下Operator纔會chain在一起?
爲了更高效地分佈式執行,Flink會盡可能地將operator的subtask鏈接(chain)在一起形成task。每個task在一個線程中執行。將operators鏈接成task是非常有效的優化:它能減少線程之間的切換,減少消息的序列化/反序列化,減少數據在緩衝區的交換,減少了延遲的同時提高整體的吞吐量。

兩個operator chain在一起的的條件:

上下游的並行度一致
下游節點的入度爲1 (也就是說下游節點沒有來自其他節點的輸入)
上下游節點都在同一個 slot group 中(下面會解釋 slot group)
下游節點的 chain 策略爲 ALWAYS(可以與上下游鏈接,map、flatmap、filter等默認是ALWAYS)
上游節點的 chain 策略爲 ALWAYS 或 HEAD(只能與下游鏈接,不能與上游鏈接,Source默認是HEAD)
兩個節點間數據分區方式是 forward(參考理解數據流的分區)
用戶沒有禁用 chain
關於源碼篇:建議去讀源碼找答案,如果沒讀過源碼,答案沒有意義。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章