新聞中心
本文轉(zhuǎn)載自微信公眾號(hào)「數(shù)倉寶貝庫」,作者張利兵。轉(zhuǎn)載本文請(qǐng)聯(lián)系數(shù)倉寶貝庫公眾號(hào)。

一架構(gòu)介紹
Flink系統(tǒng)架構(gòu)主要分為APIs & Libraries、Core和Deploy三層,如圖1所示,其中APIs層主要實(shí)現(xiàn)了面向流處理對(duì)應(yīng)的DataStream API,面向批處理對(duì)應(yīng)的DataSet API。Libraries層也被稱作Flink應(yīng)用組件層,是根據(jù)API層的劃分,在API層之上構(gòu)建滿足了特定應(yīng)用領(lǐng)域的計(jì)算框架,分別對(duì)應(yīng)了面向流處理和面向批處理兩類,其中面向流處理支持CEP(復(fù)雜事件處理)、基于類似SQL的操作(基于Table的關(guān)系操作);面向批處理支持Flink ML(機(jī)器學(xué)習(xí)庫)、Gelly(圖處理)。運(yùn)行時(shí)層提供了Flink計(jì)算的全部核心實(shí)現(xiàn),例如支持分布式Stream作業(yè)執(zhí)行、JobGraph到ExecutionGraph的映射和調(diào)度等,為API層提供了基礎(chǔ)服務(wù)。Deploy層支持多種部署模式,包括本地、集群(Standalone、YARN、Kubernetes)及云部署(GCE/EC2)。
圖1 Flink整體架構(gòu)
1、編程接口
Flink提供了多種抽象的編程接口,適用于不同層級(jí)的用戶。數(shù)據(jù)分析人員和偏向業(yè)務(wù)的數(shù)據(jù)開發(fā)人員可以使用Flink SQL定義流式作業(yè)。如圖2所示,F(xiàn)link編程接口分為4層。
圖2 Flink編程接口抽象
Flink SQL
一項(xiàng)大數(shù)據(jù)技術(shù)如果想被用戶接受和使用,除了應(yīng)具有架構(gòu)理念之外,另一點(diǎn)非常重要的就是要具有非常好的易用性。我們知道雖然Pig中的操作更加靈活和高效,但是在都滿足數(shù)據(jù)處理需求的前提下,數(shù)據(jù)開發(fā)者更愿意選擇Hive作為大數(shù)據(jù)處理的開發(fā)工具。其中最重要的原因是,Hive能夠基于SQL標(biāo)準(zhǔn)進(jìn)行拓展,提出了HQL語言,這就讓很多只會(huì)SQL的用戶也能夠快速掌握大數(shù)據(jù)處理技術(shù)。因此Hive技術(shù)很快得到普及。
對(duì)于Flink同樣如此,如果想贏得更多的用戶,就必須不斷增強(qiáng)易用性。FlinkSQL基于關(guān)系型概念構(gòu)建流式和離線處理應(yīng)用,使用戶能夠更加簡單地通過SQL構(gòu)建Flink作業(yè)。
Table API
Flink SQL解析生成邏輯執(zhí)行計(jì)劃和物理執(zhí)行計(jì)劃,然后轉(zhuǎn)換為Table之間的操作,最終轉(zhuǎn)換為JobGraph并運(yùn)行在集群上。Table API和Spark中的DataSet/DataFrame接口類似,都提供了面向領(lǐng)域語言的編程接口。相比Flink SQL,Table API更加靈活,既可以在Java & Scala SDK中與DataStream和DataSet API相互轉(zhuǎn)換,也能結(jié)合Flink SQL進(jìn)行數(shù)據(jù)處理。
DataStream & DataSet API
在早期的Flink版本中,DataSet API和DataStream API分別用于流處理和批處理場景。DataSet用于處理離線數(shù)據(jù)集,DataStream用于處理流數(shù)據(jù)集。DataFlow模型希望使用同一套流處理框架統(tǒng)一處理有界和無界數(shù)據(jù),那么為什么Flink還要抽象出兩套編程接口來處理有界數(shù)據(jù)集和無界數(shù)據(jù)集呢?這也是近年來Flink社區(qū)不斷探討的話題。目前Table和SQL API層面雖然已經(jīng)能夠做到批流一體,但這僅是在邏輯層面上的,最終還是會(huì)轉(zhuǎn)換成DataSet API和DataStream API對(duì)應(yīng)的作業(yè)。后期Flink社區(qū)將逐漸通過DataStream處理有界數(shù)據(jù)集和無界數(shù)據(jù)集,社區(qū)已經(jīng)在1.11版本中對(duì)DataStream API中的SourceFunction接口進(jìn)行了重構(gòu),使DataStream可以接入和處理有界數(shù)據(jù)集。在后期的版本中,F(xiàn)link將逐步實(shí)現(xiàn)真正意義上的批流一體化。
Stateful Processing Function接口
Stateful Processing Function接口提供了強(qiáng)大且靈活的編程能力,在其中可以直接操作狀態(tài)數(shù)據(jù)、TimeService等服務(wù),同時(shí)可以注冊(cè)事件時(shí)間和處理時(shí)間回調(diào)定時(shí)器,使程序能夠?qū)崿F(xiàn)更加復(fù)雜的計(jì)算。使用Stateful Processing Function接口需要借助DataStream API。雖然Stateful Processing Function接口靈活度很高,但是接口使用復(fù)雜度也相對(duì)較高,且在DataStream API中已經(jīng)基于Stateful Process Function接口封裝了非常豐富的算子,這些算子可以直接使用,因此,除非用戶需要自定義比較復(fù)雜的算子(如直接操作狀態(tài)數(shù)據(jù)等),否則無須使用Stateful Processing Function接口開發(fā)Flink作業(yè)。
2、運(yùn)行時(shí)執(zhí)行引擎
用戶使用組件棧和接口編寫的Flink作業(yè)最終都會(huì)在客戶端轉(zhuǎn)換成JobGraph對(duì)象,然后提交到集群中運(yùn)行。除了任務(wù)的提交和運(yùn)行之外,運(yùn)行時(shí)還包含資源管理器Resource-Manager以及負(fù)責(zé)接收和執(zhí)行Task的TaskManager,這些服務(wù)各司其職,相互合作。運(yùn)行時(shí)提供了不同類型(有界和無界)作業(yè)的執(zhí)行和調(diào)度功能,最終將任務(wù)拆解成Task執(zhí)行和調(diào)度。同時(shí),運(yùn)行時(shí)兼容了不同類型的集群資源管理器,可以提供不同的部署方式,并統(tǒng)一管理Slot計(jì)算資源。
3、物理部署層
物理部署層的主要功能是兼容不同的資源管理器,如支持集群部署模式的Hadoop YARN、Kubernetes及Standalone等。這些資源管理器能夠?yàn)樵贔link運(yùn)行時(shí)上運(yùn)行的作業(yè)提供Slot計(jì)算資源。第4章會(huì)重點(diǎn)介紹Flink物理部署層的實(shí)現(xiàn),幫助大家了解如何將運(yùn)行時(shí)運(yùn)行在不同的資源管理器上并對(duì)資源管理器提供的計(jì)算資源進(jìn)行有效管理。
二Flink集群架構(gòu)
如圖3所示,F(xiàn)link集群主要包含3部分:JobManager、TaskManager和客戶端,三者均為獨(dú)立的JVM進(jìn)程。Flink集群啟動(dòng)后,會(huì)至少啟動(dòng)一個(gè)JobManager和多個(gè)Task-Manager??蛻舳藢⑷蝿?wù)提交到JobManager,JobManager再將任務(wù)拆分成Task并調(diào)度到各個(gè)TaskManager中執(zhí)行,最后TaskManager將Task執(zhí)行的情況匯報(bào)給JobManager。
圖3 Flink集群架構(gòu)圖
客戶端是Flink專門用于提交任務(wù)的客戶端實(shí)現(xiàn),可以運(yùn)行在任何設(shè)備上,并且兼容Windows、macOS、Linux等操作系統(tǒng),只需要運(yùn)行環(huán)境與JobManager之間保持網(wǎng)絡(luò)暢通即可。用戶可以通過./bin/f?link run命令或Scala Shell交互式命令行提交作業(yè)。客戶端會(huì)在內(nèi)部運(yùn)行提交的作業(yè),然后基于作業(yè)的代碼邏輯構(gòu)建JobGraph結(jié)構(gòu),最終將JobGraph提交到運(yùn)行時(shí)中運(yùn)行。JobGraph是客戶端和集群運(yùn)行時(shí)之間約定的統(tǒng)一抽象數(shù)據(jù)結(jié)構(gòu),也就是說,不管是什么類型的作業(yè),都會(huì)通過客戶端將提交的應(yīng)用程序構(gòu)建成JobGraph結(jié)構(gòu),最后提交到集群上運(yùn)行。
JobManager是整個(gè)集群的管理節(jié)點(diǎn),負(fù)責(zé)接收和執(zhí)行來自客戶端提交的JobGraph。JobManager也會(huì)負(fù)責(zé)整個(gè)任務(wù)的Checkpoint協(xié)調(diào)工作,內(nèi)部負(fù)責(zé)協(xié)調(diào)和調(diào)度提交的任務(wù),并將JobGraph轉(zhuǎn)換為ExecutionGraph結(jié)構(gòu),然后通過調(diào)度器調(diào)度并執(zhí)行ExecutionGraph的節(jié)點(diǎn)。ExecutionGraph中的ExecutionVertex節(jié)點(diǎn)會(huì)以Task的形式在TaskManager中執(zhí)行。
除了對(duì)Job的調(diào)度和管理之外,JobManager會(huì)對(duì)整個(gè)集群的計(jì)算資源進(jìn)行統(tǒng)一管理,所有TaskManager的計(jì)算資源都會(huì)注冊(cè)到JobManager節(jié)點(diǎn)中,然后分配給不同的任務(wù)使用。當(dāng)然,JobManager還具備非常多的功能,例如Checkpoint的觸發(fā)和協(xié)調(diào)等。
TaskManager作為整個(gè)集群的工作節(jié)點(diǎn),主要作用是向集群提供計(jì)算資源,每個(gè)TaskManager都包含一定數(shù)量的內(nèi)存、CPU等計(jì)算資源。這些計(jì)算資源會(huì)被封裝成Slot資源卡槽,然后通過主節(jié)點(diǎn)中的ResourceManager組件進(jìn)行統(tǒng)一協(xié)調(diào)和管理,而任務(wù)中并行的Task會(huì)被分配到Slot計(jì)算資源中。
根據(jù)底層集群資源管理器的不同,TaskManager的啟動(dòng)方式及資源管理形式也會(huì)有所不同。例如,在基于Standalone模式的集群中,所有的TaskManager都是按照固定數(shù)量啟動(dòng)的;而YARN、Kubernetes等資源管理器上創(chuàng)建的Flink集群則支持按需動(dòng)態(tài)啟動(dòng)TaskManager節(jié)點(diǎn)。
三核心概念
1、有狀態(tài)計(jì)算
在Flink架構(gòu)體系中,有狀態(tài)計(jì)算是非常重要的特性之一。如圖4所示,有狀態(tài)計(jì)算是指在程序計(jì)算過程中,程序內(nèi)部存儲(chǔ)計(jì)算產(chǎn)生的中間結(jié)果,并將其提供給后續(xù)的算子進(jìn)行計(jì)算。狀態(tài)數(shù)據(jù)可以存儲(chǔ)在本地內(nèi)存中,也可以存儲(chǔ)在第三方存儲(chǔ)介質(zhì)中,例如Flink已經(jīng)實(shí)現(xiàn)的RocksDB。
圖4 有狀態(tài)處理和無狀態(tài)處理
和有狀態(tài)計(jì)算不同,無狀態(tài)計(jì)算不會(huì)存儲(chǔ)計(jì)算過程中產(chǎn)生的結(jié)果,也不會(huì)將結(jié)果用于下一步計(jì)算。程序只會(huì)在當(dāng)前的計(jì)算流程中執(zhí)行,計(jì)算完成就輸出結(jié)果,然后接入下一條數(shù)據(jù),繼續(xù)處理。
無狀態(tài)計(jì)算實(shí)現(xiàn)的復(fù)雜度相對(duì)較低,實(shí)現(xiàn)起來也比較容易,但是無法應(yīng)對(duì)比較復(fù)雜的業(yè)務(wù)場景,例如處理實(shí)時(shí)CEP問題,按分鐘、小時(shí)、天進(jìn)行聚合計(jì)算,求取最大值、均值等聚合指標(biāo)等。如果不借助Flink內(nèi)部提供的狀態(tài)存儲(chǔ),一般都需要通過外部數(shù)據(jù)存儲(chǔ)介質(zhì),常見的有Redis等鍵值存儲(chǔ)系統(tǒng),才能完成復(fù)雜指標(biāo)的計(jì)算。
和Storm等流處理框架不同,F(xiàn)link支持有狀態(tài)計(jì)算,可以應(yīng)對(duì)更加復(fù)雜的數(shù)據(jù)計(jì)算場景。
2、時(shí)間概念與水位線機(jī)制
在DataFlow模型中,時(shí)間會(huì)被分為事件時(shí)間和處理時(shí)間兩種類型。如圖5所示,F(xiàn)link中的時(shí)間概念基本和DataFlow模型一致,且Flink在以上兩種時(shí)間概念的基礎(chǔ)上增加了進(jìn)入時(shí)間(ingestion time)的概念,也就是數(shù)據(jù)接入到Flink系統(tǒng)時(shí)由源節(jié)點(diǎn)產(chǎn)生的時(shí)間。
圖5 Flink時(shí)間概念
事件時(shí)間指的是每個(gè)事件在其生產(chǎn)設(shè)備上發(fā)生的時(shí)間。通常在進(jìn)入Flink之前,事件時(shí)間就已經(jīng)嵌入數(shù)據(jù)記錄,后續(xù)計(jì)算從每條記錄中提取該時(shí)間?;谑录r(shí)間,我們可以通過水位線對(duì)亂序事件進(jìn)行處理。事件時(shí)間能夠準(zhǔn)確地反映事件發(fā)生的先后關(guān)系,這對(duì)流處理系統(tǒng)而言是非常重要的。在涉及較多的網(wǎng)絡(luò)傳輸時(shí),在傳輸過程中不可避免地會(huì)發(fā)生數(shù)據(jù)發(fā)送順序改變,最終導(dǎo)致流系統(tǒng)統(tǒng)計(jì)結(jié)果出現(xiàn)偏差,從而很難通過實(shí)時(shí)計(jì)算的方式得到正確的統(tǒng)計(jì)結(jié)果。
處理時(shí)間是指執(zhí)行相應(yīng)算子操作的機(jī)器系統(tǒng)時(shí)間。當(dāng)應(yīng)用基于處理時(shí)間運(yùn)行時(shí),所有基于時(shí)間的算子操作(如時(shí)間窗口)將使用運(yùn)行相應(yīng)算子機(jī)器的系統(tǒng)時(shí)鐘。例如,應(yīng)用程序在上午9:15運(yùn)行,則第一個(gè)每小時(shí)處理時(shí)間窗口包括在上午9:15到上午10:00之間處理的事件,下一個(gè)窗口包括在上午10:00到11:00之間處理的事件。
處理時(shí)間是最簡單的時(shí)間概念,不需要在流和機(jī)器之間進(jìn)行協(xié)調(diào),它提供了最佳的性能和最低的延遲。但在分布式和異步環(huán)境中,處理時(shí)間不能提供確定性,因?yàn)樗菀资艿接涗浀竭_(dá)系統(tǒng)的速度(例如從消息隊(duì)列到達(dá)系統(tǒng))以及系統(tǒng)內(nèi)算子之間流動(dòng)速度的影響。
接入時(shí)間是指數(shù)據(jù)接入Flink系統(tǒng)的時(shí)間,它由SourceOperator自動(dòng)根據(jù)當(dāng)前時(shí)鐘生成。后面所有與時(shí)間相關(guān)的Operator算子都能夠基于接入時(shí)間完成窗口統(tǒng)計(jì)等操作。接入時(shí)間的使用頻率并不高,當(dāng)接入的事件不具有事件時(shí)間時(shí),可以借助接入時(shí)間來處理數(shù)據(jù)。
相比于處理時(shí)間,接入時(shí)間的實(shí)現(xiàn)成本較高,但是它的數(shù)據(jù)只產(chǎn)生一次,且不同窗口操作可以基于統(tǒng)一的時(shí)間戳,這可以在一定程度上避免處理時(shí)間過度依賴處理算子的時(shí)鐘的問題。
不同于事件時(shí)間,接入時(shí)間不能完全刻畫出事件產(chǎn)生的先后關(guān)系。在Flink內(nèi)部,接入時(shí)間只是像事件時(shí)間一樣對(duì)待和處理,會(huì)自動(dòng)分配時(shí)間戳和生成水位線。因此,基于接入時(shí)間并不能完全處理亂序時(shí)間和遲到事件。
本文摘編于《Flink設(shè)計(jì)與實(shí)現(xiàn):核心原理與源碼解析》,經(jīng)出版方授權(quán)發(fā)布。
新聞名稱:雙維度剖析Flink整體架構(gòu)
地址分享:http://m.fisionsoft.com.cn/article/dhhjgeg.html


咨詢
建站咨詢
