上一章節(jié)已經(jīng)說過在Flink里面任務(wù)調(diào)度原理,這里面我們看到具體來說還有很多細節(jié)沒有完整地說明白,比方說前面提到的TaskManager里面的slot到底是怎么去完成任務(wù)的,還有執(zhí)行圖到底做了哪些優(yōu)化和調(diào)整呢,這些部分都是我們要考慮的問題,所以這一章節(jié),把一些細化的概念做一些分析。
首先來說slots,在之前的學(xué)習(xí),我們知道了每一個TaskManager都是干活的進程,它其實就是一JVM進程,那么在干活的過程中,一個JVM進程還能做多線程處理,所以它的內(nèi)部是:在不同的線程上去執(zhí)行一個或者多個它的子任務(wù)。而這批子任務(wù),這個線程到底能執(zhí)行多少個呢,為了控制內(nèi)部線程運行子任務(wù)的個數(shù),就提出了slots概念。slots就是TaskManager的固定大小資源的一個集合。ResourceManager在做資源分配管理的時候,最小的單位就是slot。那么接下來就看下ResourceManager是如何分配slot的。
一般的方式,我們按照每一個TaskManager機器的性能,它所含有的資源來配置slot。slot相當(dāng)于它所有資源的一個子集,這個子集在執(zhí)行過程中,就是一個隔離開的獨立的子任務(wù)(線程)。相當(dāng)于是用slot把不同的子任務(wù)之間做了一個隔離。如果機器的內(nèi)存很大,cpu數(shù)量也多,那么就可以讓它同時并行執(zhí)行任務(wù)分配更多的slot。
第一點我們要注意的是,slot隔離主要是對內(nèi)存的隔離,CPU本身是不做隔離的,CPU在不同的slot之間是可以共享的。slot內(nèi)存是平均分配的,比如機器上有16G內(nèi)存,如果劃分4個slot的話,那每個slot就是4G內(nèi)存了。如果每個slot內(nèi)存太小的話,任務(wù)就執(zhí)行不下去了,內(nèi)存直接被撐爆這個是完全有可能的。
所以在劃分內(nèi)存方面需要我們?nèi)タ剂康?,我們要根?jù)我們執(zhí)行任務(wù)的復(fù)雜程度,占用資源的角度和我們本身的機器它本身所有的資源大小做一個整體的分配。確定TaskManager到底分成幾個slot?,F(xiàn)在我們大部分機器其實內(nèi)存還好,為了避免不同的slot之間共享CPU導(dǎo)致我們資源本身負載的程度不高,這時我們往往按照CPU的數(shù)量來分配多少個slot。
第二點要注意的是,默認(rèn)情況下,F(xiàn)link允許子任務(wù)共享slot,即使它們是不同人物的子任務(wù)。這樣的結(jié)果是,一個slot可以保存作業(yè)的整個管道。Task Slot是靜態(tài)的概念,是指TaskManager具有并發(fā)執(zhí)行能力。
slot分配目的:我們其實是想要資源能夠更平均地分配到我們的任務(wù)上,能夠讓我們的資源利用率能夠更高。
舉例說明,比如在我們所有的算子操作里面,有一些Source和map這樣的任務(wù),它相對比較簡單,我們把它們叫做非資源密集型的,對資源占用率不是那么高,另外一些任務(wù),比如keyBy()/window()這些聚合操作相對來講,資源占用率較高,它是資源密集型任務(wù)。所以為了防止非資源密集型任務(wù)一直處在空閑的狀態(tài)(等待狀態(tài)),為了讓這些空閑的資源能夠利用起來,我們可以將所有的子任務(wù)都分配到各個slot上,這樣每個slot里有資源密集型任務(wù)和非資源密集型任務(wù)。都會有簡單和復(fù)雜的任務(wù),這樣所有的slot資源利用率都差不多,就都不會空閑了。
允許slot共享的好處:
1.可以獲得更好的資源利用率,不會出現(xiàn)slot之間閑的閑,累的累這種情況??梢宰屗麄兠恳粋€slot都差不多忙,具體每個slot里面先忙什么后忙什么那就看自己調(diào)度看執(zhí)行順序了。
2.JobManager拿到任務(wù)執(zhí)行計劃后,它如何確定到底需要多少個slot,這時它只要看整個作業(yè)里面,并行度最高的那個算子設(shè)置的并行度就可以了,只要滿足它的需求,別的就都能滿足了。
下面圖片展示了TaskManager分配slot任務(wù)和優(yōu)化后的對比情況:
優(yōu)化前:

優(yōu)化后:

優(yōu)化舉例:
假如我們有3個TaskManager,我們的機器能力是每個TaskManager能夠分配3個slot,那么一共就是9個slot,而如果我們設(shè)置一個slot,那么任務(wù)分配情況如下圖:

我們可以看到,有9個slot,只用到了一個slot,這顯然分配不均勻。
如果我們?nèi)衷O(shè)置并行度為2,那么所有的任務(wù)都被分到了兩個slot里。如下圖:

可以看到,還有空白的slot,這個效果也不是很好
如果要分配充分一些,我們要充分利用它的并行的能力,我們應(yīng)該把并行度設(shè)置成9,它的并發(fā)度就能夠得到最大的利用率,如下圖:

這樣,并發(fā)度看起來就都利用起來了,但這樣最后就是最好的嗎,并不是的。因為我們看到sink算子,是做輸出的,假如這個sink是寫入外部文件,那么這個sink并行在9個slot里,并行地寫,那么這個文件可能就會出現(xiàn)一個問題,我們要寫的數(shù)據(jù)就亂了。這時我們要做的是把sink并行度調(diào)低,我們可以把sink的并行度單獨設(shè)置為1,如下圖:

這樣,最后的狀態(tài)是前面兩個任務(wù),所有的并行度都是9,而只有最后一個sink任務(wù)并行度是1.