日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

flink运行原理_浅谈Flink分布式运行时和数据流图的并行化

發(fā)布時(shí)間:2024/1/23 编程问答 33 豆豆
生活随笔 收集整理的這篇文章主要介紹了 flink运行原理_浅谈Flink分布式运行时和数据流图的并行化 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

本文將以WordCount的案例為主線,主要介紹Flink的設(shè)計(jì)和運(yùn)行原理。關(guān)于Flink WordCount程序可以參考我之前的文章:讀取Kafka實(shí)時(shí)數(shù)據(jù)流,實(shí)現(xiàn)Flink WordCount。閱讀完本文后,讀者可以對(duì)Flink的分布式運(yùn)行時(shí)有一個(gè)全面的認(rèn)識(shí)。

原創(chuàng)不易,轉(zhuǎn)載請(qǐng)注明出處。對(duì)大數(shù)據(jù)和AI感興趣的朋友可以加我的微信 aistevelu,相互交流學(xué)習(xí)。

1 Flink數(shù)據(jù)流圖簡(jiǎn)介

1.1 Flink作業(yè)的邏輯視圖

在大數(shù)據(jù)領(lǐng)域,詞頻統(tǒng)計(jì)(WordCount)程序就像是一個(gè)編程語(yǔ)言的HelloWorld程序,它展示了一個(gè)大數(shù)據(jù)引擎的基本規(guī)范。麻雀雖小,五臟俱全,從這個(gè)樣例中,我們可以一窺Flink設(shè)計(jì)和運(yùn)行原理。

圖 1 Flink樣例程序示意圖

如圖 1所示,程序分為三大部分,第一部分讀取數(shù)據(jù)源(Source),第二部分對(duì)數(shù)據(jù)做轉(zhuǎn)換操作(Transformation),最后將轉(zhuǎn)換結(jié)果輸出到一個(gè)目的地(Sink)。 代碼中的方法被稱為算子(Operator),是Flink提供給程序員的接口,程序員需要通過這些算子對(duì)數(shù)據(jù)進(jìn)行操作。Source算子讀取數(shù)據(jù)源中的數(shù)據(jù),數(shù)據(jù)源可以是數(shù)據(jù)流、也可以存儲(chǔ)在文件系統(tǒng)中的文件。Transformation算子對(duì)數(shù)據(jù)進(jìn)行必要的計(jì)算處理。Sink算子將處理結(jié)果輸出,數(shù)據(jù)一般被輸出到數(shù)據(jù)庫(kù)、文件系統(tǒng)或下一個(gè)數(shù)據(jù)流程序。

我們可以把算子理解為1 + 2 運(yùn)算中的加號(hào),加號(hào)(+)是這個(gè)算子的一個(gè)符號(hào)表示,它表示對(duì)數(shù)字1和數(shù)字2做加法運(yùn)算。同樣,在Flink或Spark這樣的大數(shù)據(jù)引擎中,算子對(duì)數(shù)據(jù)進(jìn)行某種操作,程序員可以根據(jù)自己的需求調(diào)用合適的算子,完成所需計(jì)算任務(wù)。常用的算子有map、flatMap、keyBy、timeWindow等,它們分別對(duì)數(shù)據(jù)流執(zhí)行不同類型的操作。

我們先對(duì)這個(gè)樣例程序中各個(gè)算子做一個(gè)簡(jiǎn)單的介紹,關(guān)于這些算子的具體使用方式將在后續(xù)文章中詳細(xì)說明。

  • flatMap

flatMap對(duì)輸入進(jìn)行處理,生成零到多個(gè)輸出。這里是一個(gè)簡(jiǎn)單的分詞過程,對(duì)一行字符串按照空格切分,生成一個(gè)(word, 1)的二元組。

  • keyBy

keyBy根據(jù)某個(gè)Key對(duì)數(shù)據(jù)重新分組。本例中是將flatMap生成的二元組(word, 1)中第一項(xiàng)作為Key,相同的單詞會(huì)被分到同一組。

  • timeWindow

timeWindow是時(shí)間窗口函數(shù),用來(lái)界定對(duì)多長(zhǎng)時(shí)間之內(nèi)的數(shù)據(jù)做統(tǒng)計(jì)。

  • sum

sum為求和函數(shù)。sum(1)表示對(duì)二元組中第二個(gè)元素求和,因?yàn)榻?jīng)過前面的keyBy,所有相同的單詞都被分到了一起,因此,在這個(gè)分組內(nèi),將單詞出現(xiàn)次數(shù)做加和,就得到出現(xiàn)的總次數(shù)。

圖 2 WordCont程序的邏輯視圖

在程序?qū)嶋H運(yùn)行前,Flink會(huì)將用戶編寫的代碼做一個(gè)簡(jiǎn)單處理,生成一個(gè)如圖2所示的邏輯視圖。圖 2展示了WordCount程序中,數(shù)據(jù)從不同算子間流動(dòng)的情況。圖中,圓圈代表算子,圓圈間的箭頭代表數(shù)據(jù)流,數(shù)據(jù)流在Flink程序中經(jīng)過不同算子的計(jì)算,最終生成為目標(biāo)數(shù)據(jù)。其中,keyBy、timeWindow和sum共同組成了一個(gè)時(shí)間窗口上的聚合操作,被歸結(jié)為一個(gè)算子。我們可以在Flink的Web UI中,點(diǎn)擊一個(gè)作業(yè),查看這個(gè)作業(yè)的邏輯視圖。

對(duì)于詞頻統(tǒng)計(jì)這個(gè)案例,邏輯上來(lái)講無(wú)非是對(duì)數(shù)據(jù)流中的單詞做提取,然后使用一個(gè)Key-Value結(jié)構(gòu)對(duì)單詞做詞頻計(jì)數(shù),最后輸出結(jié)果即可,這樣的邏輯本可以用幾行代碼完成,改成使用算子形式,反而讓新人看著一頭霧水,為什么一定要用算子的形式來(lái)寫程序呢?實(shí)際上,算子進(jìn)化成當(dāng)前這個(gè)形態(tài),就像人類從石塊計(jì)數(shù),到手指計(jì)數(shù),到算盤計(jì)數(shù),再到計(jì)算機(jī)計(jì)數(shù)這樣的進(jìn)化過程一樣,盡管更低級(jí)的方式可以完成一定的計(jì)算任務(wù),但是隨著計(jì)算規(guī)模的增長(zhǎng),古老的計(jì)數(shù)方式存在著低效的弊端,無(wú)法完成更高級(jí)別和更大規(guī)模的計(jì)算需求。試想,如果我們不使用大數(shù)據(jù)引擎提供的算子,而是自己實(shí)現(xiàn)一套上述的計(jì)算邏輯,盡管我們可以快速完成當(dāng)前的詞頻統(tǒng)計(jì)的任務(wù),但是當(dāng)面臨一個(gè)新計(jì)算任務(wù)時(shí),我們需要重新編寫程序,完成一整套計(jì)算任務(wù)。我們自己編寫代碼的橫向擴(kuò)展性可能很低,當(dāng)輸入數(shù)據(jù)暴增時(shí),我們需要做很大改動(dòng),以部署在更多機(jī)器上。

大數(shù)據(jù)引擎的算子對(duì)計(jì)算做了一些抽象,對(duì)于新人來(lái)說有一定學(xué)習(xí)成本,而一旦掌握這門技術(shù),人們所能處理的數(shù)據(jù)規(guī)模將成倍增加。大數(shù)據(jù)引擎的算子出現(xiàn),正是針對(duì)數(shù)據(jù)分布在多個(gè)節(jié)點(diǎn)的大數(shù)據(jù)場(chǎng)景下,需要一種統(tǒng)一的計(jì)算描述語(yǔ)言來(lái)對(duì)數(shù)據(jù)做計(jì)算而進(jìn)化出的新計(jì)算形態(tài)。基于Flink的算子,我們可以定義一個(gè)數(shù)據(jù)流的邏輯視圖,以此完成對(duì)大數(shù)據(jù)的計(jì)算。剩下那些數(shù)據(jù)交換、橫向擴(kuò)展、故障恢復(fù)等問題全交由大數(shù)據(jù)引擎來(lái)解決。

1.2 從邏輯視圖到物理執(zhí)行

在絕大多數(shù)的大數(shù)據(jù)處理場(chǎng)景下,一臺(tái)機(jī)器節(jié)點(diǎn)無(wú)法處理所有數(shù)據(jù),數(shù)據(jù)被切分到多臺(tái)節(jié)點(diǎn)上。在大數(shù)據(jù)領(lǐng)域,當(dāng)數(shù)據(jù)量大到超過單臺(tái)機(jī)器處理能力時(shí),需要將一份數(shù)據(jù)切分到多個(gè)分區(qū)(Partition)上,每個(gè)分區(qū)分布在一臺(tái)虛擬機(jī)或物理機(jī)上。

前一小節(jié)已經(jīng)提到,大數(shù)據(jù)引擎的算子提供了編程接口,我們可以使用算子構(gòu)建數(shù)據(jù)流的邏輯視圖。考慮到數(shù)據(jù)分布在多個(gè)節(jié)點(diǎn)的情況,邏輯視圖只是一種抽象,需要將邏輯視圖轉(zhuǎn)化為物理執(zhí)行圖,才能在分布式環(huán)境下執(zhí)行。

圖 3 樣例程序物理執(zhí)行示意圖

圖 3為WordCount程序的物理執(zhí)行圖,這里數(shù)據(jù)流分布在2個(gè)分區(qū)上。箭頭部分表示數(shù)據(jù)流分區(qū),圓圈部分表示算子在分區(qū)上的算子子任務(wù)(Operator Subtask)。從邏輯視圖變?yōu)槲锢韴?zhí)行圖后,FlatMap算子在每個(gè)分區(qū)都有一個(gè)算子子任務(wù),以處理該分區(qū)上的數(shù)據(jù):FlatMap[1/2]算子子任務(wù)處理第一個(gè)數(shù)據(jù)流分區(qū)上的數(shù)據(jù),以此類推。

算子子任務(wù)又被稱為算子實(shí)例,一個(gè)算子在并行執(zhí)行時(shí),會(huì)有多個(gè)算子實(shí)例。即使輸入數(shù)據(jù)增多,我們也可以通過部署更多的算子實(shí)例來(lái)進(jìn)行橫向擴(kuò)展。從圖 3中可以看到,除去Sink外的算子都被分成了2個(gè)算子實(shí)例,他們的并行度(Parallelism)為2,Sink算子的并行度為1。并行度是可以被設(shè)置的,當(dāng)設(shè)置某個(gè)算子的并行度為2時(shí),也就意味著有這個(gè)算子有2個(gè)算子子任務(wù)(或者說2個(gè)算子實(shí)例)并行執(zhí)行。實(shí)際應(yīng)用中一般根據(jù)輸入數(shù)據(jù)量的大小,計(jì)算資源的多少等多方面的因素來(lái)設(shè)置并行度。

注意,在本例中,為了演示,我們把所有算子的并行度設(shè)置為了2:env.setParallelism(2);,把最后輸出的并行度設(shè)置成了1:wordCount.print().setParallelism(1);。如果不單獨(dú)設(shè)置print的并行度的話,它的并行度也是2。

算子子任務(wù)是Flink物理執(zhí)行的基本單元,算子子任務(wù)之間是相互獨(dú)立的,某個(gè)算子子任務(wù)有自己的線程,不同算子子任務(wù)可能分布在不同的節(jié)點(diǎn)上。后文在Flink的資源分配部分我們還會(huì)重點(diǎn)介紹算子子任務(wù)。

1.3 數(shù)據(jù)交換策略

圖 3中出現(xiàn)了數(shù)據(jù)流動(dòng)的現(xiàn)象,即數(shù)據(jù)在不同的算子子任務(wù)上進(jìn)行著數(shù)據(jù)交換。無(wú)論是Hadoop、Spark還是Flink,都都會(huì)涉及到數(shù)據(jù)交換策略。常見的據(jù)交換策略有4種,如圖 4所示。

圖 4 Flink數(shù)據(jù)交換策略

  • 前向傳播(Forward):前一個(gè)算子子任務(wù)將數(shù)據(jù)直接傳遞給后一個(gè)算子子任務(wù),數(shù)據(jù)不存在跨分區(qū)的交換,也避免了因數(shù)據(jù)交換產(chǎn)生的各類開銷,圖 3中Source和和FlatMap之間就是這樣的情形。
  • 按Key分組(Key-Based):數(shù)據(jù)以(Key, Value)形式存在,該策略將所有數(shù)據(jù)進(jìn)行分組,相同Key的數(shù)據(jù)會(huì)被分到一組,發(fā)送到同一個(gè)分區(qū)上。WordCount程序中,keyBy將單詞作為Key,把相同單詞都發(fā)送到同一分區(qū),以方便后續(xù)算子的聚合統(tǒng)計(jì)。
  • 廣播(Broadcast):將某份數(shù)據(jù)發(fā)送到所有分區(qū)上,這種策略涉及到了數(shù)據(jù)在全局的拷貝,因此非常消耗資源。
  • 隨機(jī)策略(Random):該策略將所有數(shù)據(jù)隨機(jī)均勻地發(fā)送到多個(gè)分區(qū)上,以保證數(shù)據(jù)平均分配到不同分區(qū)上。該策略通常為了防止數(shù)據(jù)傾斜到某些分區(qū),導(dǎo)致部分分區(qū)數(shù)據(jù)稀疏,另外一些分區(qū)數(shù)據(jù)擁堵。
  • 2 Flink架構(gòu)與核心組件

    為了實(shí)現(xiàn)支持分布式運(yùn)行,Flink跟其他大數(shù)據(jù)引擎一樣,采用了主從(Master-Worker)架構(gòu),運(yùn)行時(shí)主要包括兩個(gè)組件:

    ? Master是一個(gè)Flink作業(yè)的主進(jìn)程。它起到了協(xié)調(diào)管理的作用。

    ? TaskManager,又被稱為Worker或Slave,是執(zhí)行計(jì)算任務(wù)的進(jìn)程。它擁有CPU、內(nèi)存等計(jì)算資源。Flink作業(yè)需要將計(jì)算任務(wù)分發(fā)到多個(gè)TaskManager上并行執(zhí)行。

    下面將從作業(yè)執(zhí)行層面來(lái)分析Flink各個(gè)模塊如何工作。

    2.1 Flink作業(yè)執(zhí)行過程

    Flink為適應(yīng)不同的基礎(chǔ)環(huán)境(獨(dú)立集群、YARN、Kubernetes),在不斷的迭代開發(fā)過程中已經(jīng)逐漸形成了一個(gè)作業(yè)執(zhí)行流程。不同的基礎(chǔ)環(huán)境對(duì)計(jì)算資源的管理方式略有不同,不過都大同小異,這里以獨(dú)立集群(Standalone)為例,分析作業(yè)的分布式執(zhí)行流程。Standalone模式指Flink獨(dú)占該集群,集群上無(wú)其他任務(wù),如Spark、MapReduce等。

    圖 5 Flink作業(yè)提交流程

    在一個(gè)作業(yè)提交前,Master和TaskManager等進(jìn)程需要先被啟動(dòng)。我們可以在Flink主目錄中執(zhí)行腳本來(lái)啟動(dòng)這些進(jìn)程:bin/start-cluster.sh。Master和TaskManager被啟動(dòng)后,TaskManager需要將自己注冊(cè)給Master中的ResourceManager。這個(gè)初始化和資源注冊(cè)過程發(fā)生在單個(gè)作業(yè)提交前,我們稱之為第0步。

    接下來(lái)我們逐步分析一個(gè)Flink作業(yè)如何被提交:

  • 用戶編寫應(yīng)用程序代碼,并通過Flink客戶端(Client)提交作業(yè)。程序一般為Java或Scala語(yǔ)言,調(diào)用Flink API,構(gòu)建基于邏輯視角的數(shù)據(jù)流圖,代碼和相關(guān)配置文件被編譯打包,被提交到Master的Dispatcher,形成一個(gè)應(yīng)用作業(yè)(Application)。
  • Dispatcher接收到這個(gè)作業(yè),啟動(dòng)JobManager,這個(gè)JobManager會(huì)負(fù)責(zé)本次作業(yè)。
  • JobManager向ResourceManager申請(qǐng)本次作業(yè)所需資源。
  • 由于在第0步中TaskManager已經(jīng)向ResourceManager中注冊(cè)了資源,這時(shí)閑置的TaskManager會(huì)被反饋給JobManager。
  • JobManager將用戶作業(yè)中的邏輯視圖轉(zhuǎn)化為圖3所示的并行化的物理執(zhí)行圖,將計(jì)算任務(wù)分發(fā)部署到多個(gè)TaskManager上。至此,一個(gè)Flink作業(yè)就開始執(zhí)行了。
  • TaskManager在執(zhí)行計(jì)算任務(wù)過程中可能會(huì)與其他TaskManager交換數(shù)據(jù),會(huì)使用圖 4提到的一些數(shù)據(jù)交換策略。同時(shí),TaskManager也會(huì)將一些任務(wù)狀態(tài)信息會(huì)反饋給JobManager,這些信息包括任務(wù)啟動(dòng)、運(yùn)行或終止的狀態(tài),快照的元數(shù)據(jù)等。

    我們?cè)賹?duì)涉及到的各個(gè)組件進(jìn)行更為詳細(xì)的介紹。

    Client

    用戶一般使用客戶端(Client)提交作業(yè),比如Flink主目錄下的bin目錄中提供的命令行工具。Client會(huì)對(duì)用戶提交的Flink程序進(jìn)行預(yù)處理,并把作業(yè)提交到Flink集群上。Client提交作業(yè)時(shí)需要配置一些必要的參數(shù),比如使用Standalone還是YARN集群等。整個(gè)作業(yè)被打成了Jar包,DataStream API被轉(zhuǎn)換成了JobGraph,JobGraph是一種類似圖2的邏輯視圖。

    Dispatcher

    Dispatcher可以接收多個(gè)作業(yè),每接收一個(gè)作業(yè),Dispatcher都會(huì)為這個(gè)作業(yè)分配一個(gè)JobManager。Dispatcher對(duì)外提供一個(gè)REST式的接口,以HTTP的形式來(lái)對(duì)外提供服務(wù)。

    JobManager

    JobManager是單個(gè)Flink作業(yè)的協(xié)調(diào)者,一個(gè)作業(yè)會(huì)有一個(gè)JobManager來(lái)負(fù)責(zé)。JobManager會(huì)將Client提交的JobGraph轉(zhuǎn)化為ExceutionGraph,ExecutionGraph是類似圖3所示的可并行的物理執(zhí)行圖。JobManager會(huì)向ResourceManager申請(qǐng)必要的資源,當(dāng)獲取足夠的資源后,JobManager將ExecutionGraph以及具體的計(jì)算任務(wù)分發(fā)部署到多個(gè)TaskManager上。同時(shí),JobManager還負(fù)責(zé)管理多個(gè)TaskManager,這包括:收集作業(yè)的狀態(tài)信息,生成檢查點(diǎn),必要時(shí)進(jìn)行故障恢復(fù)等問題。

    ResourceManager

    如前文所說,Flink現(xiàn)在可以部署在Standalone、YARN或Kubernetes等環(huán)境上,不同環(huán)境中對(duì)計(jì)算資源的管理模式略有不同,Flink使用一個(gè)名為ResourceManager的模塊來(lái)統(tǒng)一處理資源分配上的問題。在Flink中,計(jì)算資源的基本單位是TaskManager上的任務(wù)槽位(Task Slot,簡(jiǎn)稱槽位Slot)。ResourceManager的職責(zé)主要是從YARN等資源提供方獲取計(jì)算資源,當(dāng)JobManager有計(jì)算需求時(shí),將空閑的Slot分配給JobManager。當(dāng)計(jì)算任務(wù)結(jié)束時(shí),ResourceManager還會(huì)重新收回這些Slot。

    TaskManager

    TaskManager是實(shí)際負(fù)責(zé)執(zhí)行計(jì)算的節(jié)點(diǎn)。一般地,一個(gè)Flink作業(yè)是分布在多個(gè)TaskManager上執(zhí)行的,單個(gè)TaskManager上提供一定量的Slot。一個(gè)TaskManager啟動(dòng)后,相關(guān)Slot信息會(huì)被注冊(cè)到ResourceManager中。當(dāng)某個(gè)Flink作業(yè)提交后,TaskManager會(huì)將空閑的Slot信息提供給JobManager。JobManager獲取到空閑Slot信息后會(huì)將具體的計(jì)算任務(wù)部署到該Slot之上,任務(wù)開始在這些Slot上執(zhí)行。在執(zhí)行過程,由于要進(jìn)行數(shù)據(jù)交換,TaskManager還要和其他TaskManager進(jìn)行必要的數(shù)據(jù)通信。

    總之,TaskManager負(fù)責(zé)具體計(jì)算任務(wù)的執(zhí)行,啟動(dòng)時(shí)它會(huì)將資源向ResourceManager注冊(cè)。

    2.2 再談邏輯視圖到物理執(zhí)行圖

    了解了Flink的分布式架構(gòu)和核心組件,這里我們從更細(xì)粒度上來(lái)介紹從邏輯視圖轉(zhuǎn)化為物理執(zhí)行圖過程,該過程可以分成四層:StreamGraph -> JobGraph -> ExecutionGraph -> 物理執(zhí)行圖。

    圖 6 WordCount程序數(shù)據(jù)流圖轉(zhuǎn)化過程

    • StreamGraph:是根據(jù)用戶編寫的代碼生成的最初的圖,用來(lái)表示一個(gè)Flink作業(yè)的拓?fù)浣Y(jié)構(gòu)。在StreamGraph中,節(jié)點(diǎn)StreamNode就是算子。
    • JobGraph:JobGraph是提交給 JobManager 的數(shù)據(jù)結(jié)構(gòu)。StreamGraph經(jīng)過優(yōu)化后生成了JobGraph,主要的優(yōu)化為,將多個(gè)符合條件的節(jié)點(diǎn)鏈接在一起作為一個(gè)JobVertex節(jié)點(diǎn),這樣可以減少數(shù)據(jù)交換所需要的傳輸開銷。這個(gè)鏈接的過程叫做算子鏈(Operator Chain),會(huì)在下一小節(jié)繼續(xù)介紹。JobVertex經(jīng)過算子鏈后,會(huì)包含一到多個(gè)算子,它輸出是IntermediateDataSet,是經(jīng)過算子處理產(chǎn)生的數(shù)據(jù)集。
    • ExecutionGraph:JobManager將 JobGraph轉(zhuǎn)化為ExecutionGraph。ExecutionGraph是JobGraph的并行化版本:假如某個(gè)JobVertex的并行度是2,那么它將被劃分為2個(gè)ExecutionVertex,ExecutionVertex表示一個(gè)算子子任務(wù),它監(jiān)控著單個(gè)子任務(wù)的執(zhí)行情況。每個(gè)ExecutionVertex會(huì)輸出一個(gè)IntermediateResultPartition,這是單個(gè)子任務(wù)的輸出,再經(jīng)過ExecutionEdge輸出到下游節(jié)點(diǎn)。ExecutionJobVertex是這些并行子任務(wù)的合集,它監(jiān)控著整個(gè)算子的運(yùn)行情況。ExecutionGraph是調(diào)度層非常核心的數(shù)據(jù)結(jié)構(gòu)。
    • 物理執(zhí)行圖:JobManager根據(jù)ExecutionGraph對(duì)作業(yè)進(jìn)行調(diào)度后,在各個(gè)TaskManager上部署具體的任務(wù),物理執(zhí)行圖并不是一個(gè)具體的數(shù)據(jù)結(jié)構(gòu)。

    可以看到,Flink在數(shù)據(jù)流圖上可謂煞費(fèi)苦心,僅各類圖就有四種之多。對(duì)于新人來(lái)說,可以不用太關(guān)心這些非常細(xì)節(jié)的底層實(shí)現(xiàn),只需要了解以下幾個(gè)核心概念:

    • Flink采用主從架構(gòu),Master起著管理協(xié)調(diào)作用,TaskManager負(fù)責(zé)物理執(zhí)行,在執(zhí)行過程中會(huì)發(fā)生一些數(shù)據(jù)交換、生命周期管理等事情。
    • 用戶調(diào)用Flink API,構(gòu)造邏輯視圖,Flink會(huì)對(duì)邏輯視圖優(yōu)化,并轉(zhuǎn)化為并行化的物理執(zhí)行圖,最后被執(zhí)行的是物理執(zhí)行圖。

    2.3 任務(wù)、算子子任務(wù)與算子鏈

    在構(gòu)造物理執(zhí)行圖的過程中,Flink會(huì)將一些算子子任務(wù)鏈接在一起,組成算子鏈。鏈接后以任務(wù)(Task)的形式被TaskManager調(diào)度執(zhí)行。使用算子鏈?zhǔn)且粋€(gè)非常有效的優(yōu)化,它可以有效降低算子子任務(wù)之間的傳輸開銷。鏈接之后形成的Task是TaskManager中的一個(gè)線程。

    圖 7 任務(wù)、子任務(wù)與算子鏈

    例如,數(shù)據(jù)從Source前向傳播到FlatMap,這中間沒有發(fā)生跨分區(qū)的數(shù)據(jù)交換,因此,我們完全可以將Source、FlatMap這兩個(gè)子任務(wù)組合在一起,形成一個(gè)Task。數(shù)據(jù)經(jīng)過keyBy發(fā)生了數(shù)據(jù)交換,數(shù)據(jù)會(huì)跨越分區(qū),因此無(wú)法將keyBy以及其后面的窗口聚合鏈接到一起。由于WindowAggregation的并行度是2,Sink的并行度為1,數(shù)據(jù)再次發(fā)生了交換,我們不能把WindowAggregation和Sink兩部分鏈接到一起。1.2節(jié)中提到,Sink的并行度是人為設(shè)置為1,如果我們把Sink的并行度也設(shè)置為2,那么是可以讓這兩個(gè)算子鏈接到一起的。

    默認(rèn)情況下,Flink會(huì)盡量將更多的子任務(wù)鏈接在一起,這樣能減少一些不必要的數(shù)據(jù)傳輸開銷。但一個(gè)子任務(wù)有超過一個(gè)輸入或發(fā)生數(shù)據(jù)交換時(shí),鏈接就無(wú)法建立。兩個(gè)算子能夠鏈接到一起是有一些規(guī)則的,感興趣的讀者可以閱讀Flink源碼中org.apache.flink.streaming.api.graph.StreamingJobGraphGenerator中的isChainable方法。StreamingJobGraphGenerator類的作用是將StreamGraph轉(zhuǎn)換為JobGraph。

    盡管將算子鏈接到一起會(huì)降低一些傳輸開銷,但是也有一些情況并不需要太多鏈接。比如,有時(shí)候我們需要將一個(gè)非常長(zhǎng)的算子鏈拆開,這樣我們就可以將原來(lái)集中在一個(gè)線程中的計(jì)算拆分到多個(gè)線程中來(lái)并行計(jì)算。Flink允許開發(fā)者手動(dòng)配置是否啟用算子鏈,或者對(duì)哪些算子使用算子鏈。

    2.4 任務(wù)槽位與計(jì)算資源

    任務(wù)槽位

    根據(jù)前文的介紹,我們已經(jīng)了解到TaskManager負(fù)責(zé)具體的任務(wù)執(zhí)行。TaskManager是一個(gè)JVM進(jìn)程,在TaskManager中可以并行運(yùn)行多個(gè)Task。在程序執(zhí)行之前,經(jīng)過優(yōu)化,部分子任務(wù)被鏈接在一起,組成一個(gè)Task。每個(gè)Task是一個(gè)線程,需要TaskManager為其分配相應(yīng)的資源,TaskManager使用任務(wù)槽位給Task分配資源。

    在解釋Flink任務(wù)槽位的概念前,我們先回顧一下進(jìn)程與線程的概念。在操作系統(tǒng)層面,進(jìn)程(Process)是進(jìn)行資源分配和調(diào)度的一個(gè)獨(dú)立單位,線程(Thread)是CPU調(diào)度的基本單位。比如,我們常用的Office Word軟件,在啟動(dòng)后就占用操作系統(tǒng)的一個(gè)進(jìn)程。Windows上可以使用任務(wù)管理器來(lái)查看當(dāng)前活躍的進(jìn)程,Linux上可以使用top命令來(lái)查看。線程是進(jìn)程的一個(gè)子集,一個(gè)線程一般專注于處理一些特定任務(wù),不獨(dú)立擁有系統(tǒng)資源,只擁有一些運(yùn)行中必要的資源,如程序計(jì)數(shù)器。一個(gè)進(jìn)程至少有一個(gè)線程,也可以有多個(gè)線程。多線程場(chǎng)景下,每個(gè)線程都處理一小個(gè)任務(wù),多個(gè)線程以高并發(fā)的方式同時(shí)處理多個(gè)小任務(wù),可以提高處理能力。

    回到Flink的槽位分配機(jī)制上,一個(gè)TaskManager是一個(gè)進(jìn)程,TaskManager可以管理一至多個(gè)Task,每個(gè)Task是一個(gè)線程,占用一個(gè)槽位。每個(gè)槽位的資源是整個(gè)TaskManager資源的子集,比如這里的TaskManager下有3個(gè)槽位,每個(gè)槽位占用TaskManager所管理的1/3的內(nèi)存,第一個(gè)槽位中的Task不會(huì)與第二個(gè)槽位中的Task互相爭(zhēng)搶內(nèi)存資源。注意,在分配資源時(shí),Flink并沒有將CPU資源明確分配給各個(gè)槽位。

    圖 8 Task Slot與Task Manager

    假設(shè)我們給WordCount程序分配兩個(gè)TaskManager,每個(gè)TaskManager又分配3個(gè)槽位,所以總共是6個(gè)槽位。結(jié)合圖 7中對(duì)這個(gè)作業(yè)的并行度設(shè)置,整個(gè)作業(yè)被劃分為5個(gè)Task,使用5個(gè)線程,這5個(gè)線程可以按照?qǐng)D 8所示的方式分配到6個(gè)槽位中。

    Flink允許用戶設(shè)置TaskManager中槽位的數(shù)目,這樣用戶就可以確定以怎樣的粒度將任務(wù)做相互隔離。如果每個(gè)TaskManager只包含一個(gè)槽位,那么運(yùn)行在該槽位內(nèi)的任務(wù)將獨(dú)享JVM。如果TaskManager包含多個(gè)槽位,那么多個(gè)槽位內(nèi)的任務(wù)可以共享JVM資源,比如共享TCP連接、心跳信息、部分?jǐn)?shù)據(jù)結(jié)構(gòu)等。官方建議將槽位數(shù)目設(shè)置為TaskManager下可用的CPU核心數(shù),那么平均下來(lái),每個(gè)槽位都能平均獲得1個(gè)CPU核心。

    槽位共享

    圖 8中展示了任務(wù)的一種資源分配方式,默認(rèn)情況下, Flink還提供了一種槽位共享(Slot Sharing)的優(yōu)化機(jī)制,進(jìn)一步優(yōu)化數(shù)據(jù)傳輸開銷,充分利用計(jì)算資源。將圖 8中的任務(wù)做槽位共享優(yōu)化后,結(jié)果如圖 9所示。

    圖 9 槽位共享示意圖

    開啟槽位共享后,Flink允許多個(gè)任務(wù)共享一個(gè)槽位。如圖 9中最左側(cè)的數(shù)據(jù)流,一個(gè)作業(yè)從Source到Sink的所有子任務(wù)都可以放置在一個(gè)槽位中,這樣數(shù)據(jù)交換成本更低。而且,對(duì)于一個(gè)數(shù)據(jù)流圖來(lái)說,Source、FlatMap等算子的計(jì)算量相對(duì)不大,WindowAggregation算子的計(jì)算量比較大,計(jì)算量較大的算子子任務(wù)與計(jì)算量較小的算子子任務(wù)可以互補(bǔ),騰出更多的槽位,分配給更多Task,這樣可以更好地利用資源。如果不開啟槽位共享,如圖8所示,計(jì)算量小的Source、FlatMap算子子任務(wù)獨(dú)占槽位,造成一定的資源浪費(fèi)。

    圖 10 槽位共享后,增大并行度,可以部署更多算子實(shí)例

    圖 8中的方式共占用5個(gè)槽位,支持槽位共享后,圖 9只占用2個(gè)槽位。為了充分利用空槽位,剩余的4個(gè)空槽位可以分配給別的作業(yè),也可以通過修改并行度來(lái)分配給這個(gè)作業(yè)。例如,這個(gè)作業(yè)的輸入數(shù)據(jù)量非常大,我們可以把并行度設(shè)為6,更多的算子實(shí)例會(huì)將這些槽位填充,如圖10所示。

    綜上,Flink的一個(gè)槽位中可能運(yùn)行一個(gè)算子子任務(wù)、也可能是被鏈接的多個(gè)子任務(wù),或者是多個(gè)子任務(wù)共享槽位,具體這個(gè)槽位上運(yùn)行哪些計(jì)算由算子鏈和槽位共享兩個(gè)優(yōu)化措施決定。

    創(chuàng)作挑戰(zhàn)賽新人創(chuàng)作獎(jiǎng)勵(lì)來(lái)咯,堅(jiān)持創(chuàng)作打卡瓜分現(xiàn)金大獎(jiǎng)

    總結(jié)

    以上是生活随笔為你收集整理的flink运行原理_浅谈Flink分布式运行时和数据流图的并行化的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。