1. 程序和數(shù)據(jù)流
Flink程序構(gòu)建的基本單元是stream和transformation(請(qǐng)注意,DataSet實(shí)質(zhì)上也是stream)。一個(gè)stream是一個(gè)中間結(jié)果,一個(gè)transformation是一個(gè)操作,該操作以一個(gè)或多個(gè)stream為輸入,計(jì)算輸出一個(gè)或多個(gè)stream為結(jié)果。
在運(yùn)行時(shí),F(xiàn)link上運(yùn)行的程序會(huì)被映射成streaming dataflows,它包含了streams和transformations操作。每個(gè)dataflow以一個(gè)或者多個(gè)source開(kāi)始,以一個(gè)或多個(gè)sink結(jié)束。dataflow類似于有向無(wú)環(huán)圖(DAG),特殊形式的環(huán)也允許通過(guò)iteration構(gòu)建。
在大多數(shù)情況下,程序中的transformation和dataflow中的操作是一一對(duì)應(yīng)關(guān)系,但有時(shí)候一個(gè)transformation可能對(duì)應(yīng)了多個(gè)操作。
1.1 并行數(shù)據(jù)流 Parallel Dataflows
Flink程序與生俱來(lái)的就是并行和分布式的。Streams被分割成stream patition, Operators被被分割成operator subtasks。這些subtasks在不同的機(jī)器(容器)上的不同的線程中運(yùn)行,彼此獨(dú)立,互不干擾。 一個(gè)操作的operator subtask的數(shù)目,被稱為parallelism(并行度)。一個(gè)stream的并行度,總是等于生成它的(operator)操作的并行度。一個(gè)Flink程序中,不同的operator可能具有不同的并行度。
- One-to-One Streams(例如source和map()之間)維護(hù)著分區(qū)和元素的順序。這意味著map操作看到的元素個(gè)數(shù)和順序跟source操作看到的元素個(gè)數(shù)和順序是相同的。
- Redistributing Streams(例如map()和keyBy、Window之間,還有keyBy、Window和sink之間)的分區(qū)發(fā)生改變。每個(gè)operator subtask把數(shù)據(jù)發(fā)送到不同的目標(biāo)subtask上,其發(fā)送的依據(jù)是選擇何種的transformation。例如keyBy操作(基于Hash重新分區(qū)),broadcast()或者 rebalance() (隨機(jī)重新分區(qū))。在一個(gè)redistributing 交換中,元素之間的順序僅僅在每一個(gè)發(fā)送-接受task對(duì)中才會(huì)被維持。
1.2 任務(wù)和操作鏈 Tasks & Operator Chains
為了達(dá)到分布式執(zhí)行的目的,F(xiàn)link把subtasks鏈在一起形成tasks。每一個(gè)任務(wù)(task)被一個(gè)線程執(zhí)行。將操作鏈在一起形成task是非常有效的優(yōu)化,它能減少線程之間的切換,提高吞吐量,降低延時(shí)。操作鏈的行為可以同API配置指定。下面的圖展示了5個(gè)sub task,以5個(gè)并行的線程來(lái)執(zhí)行。
2. 分布式執(zhí)行 Distributed Execution
Flink是一個(gè)主結(jié)構(gòu)的分布式系統(tǒng),其Master被成為JobManager,其Slave(worker)被成為TaskManager;Flink管理分配資源的單位是Slot。
2.1 集群角色 Master,Worker,Client
Flink集群?jiǎn)?dòng)后,會(huì)有兩種進(jìn)程,一種是JobManager(Master),一種是TaskManager(Worker),我們可以通過(guò)jps
或者ps -ef | grep java
命令來(lái)查看Flink進(jìn)程。
- Master進(jìn)程(JobManager),用于分布式執(zhí)行,調(diào)度任務(wù),協(xié)調(diào)檢查點(diǎn)(checkpoint),協(xié)調(diào)失敗恢復(fù)等。Flink集群中至少有一個(gè)Master進(jìn)程;為了高可用性,通常會(huì)有多個(gè)Master節(jié)點(diǎn),選舉其中一個(gè)作為leader,其余作為standby。
- Worker進(jìn)程(TaskManager),用于執(zhí)行dataflow上的task(subtask),緩存和交換數(shù)據(jù)流。TaskManager至少有一個(gè)。
Flink集群的Master進(jìn)程和Worker進(jìn)程可以通過(guò)多種方式啟動(dòng),既可以在物理機(jī)上部署啟動(dòng),也可以通過(guò)容器技術(shù)、或者像YARN這樣的資源管理框架啟動(dòng)。Worker連接到Master,告知自身可用,并等待分配任務(wù)。
Client不是Flink集群運(yùn)行時(shí)的一部分,它作為客戶端,用來(lái)準(zhǔn)備和發(fā)送數(shù)據(jù)流到Master,在這之后,客戶端可以斷開(kāi),或者保持連接接受結(jié)果數(shù)據(jù)??蛻舳顺绦蚩梢允莏ava或者Scala程序,也可以通過(guò)命令行的方式(bin/flink run...)來(lái)觸發(fā)Flink集群執(zhí)行。
2.2 資源管理 Workers, Slots, Resources
每個(gè)Worker都是一個(gè)JVM進(jìn)程,可以在不同的線程里執(zhí)行一個(gè)或者多個(gè)subtasks。Worker通過(guò)task slots來(lái)管理接受處理多少個(gè)任務(wù)。每個(gè)task slot代表了固定額度的資源,是TaskManager擁有的資源的子集。例如,一個(gè)TaskManager有3個(gè)slot,那么每個(gè)slot占據(jù)其1/3的資源。 采用slot來(lái)分配資源,避免了任務(wù)之間的資源競(jìng)爭(zhēng)。需要注意的是,F(xiàn)link的slot僅僅描述和隔離了內(nèi)存資源,并不包括CPU資源的隔離。
通過(guò)調(diào)整slot的數(shù)量,我們可以調(diào)節(jié)subtask之間的資源隔離情況。如果每個(gè)TaskManager上只有一個(gè)slot,意味著該任務(wù)將會(huì)獨(dú)占資源;如果有多個(gè)slot,意味著更多的任務(wù)共享JVM資源。同一個(gè)JVM進(jìn)程中的任務(wù)將會(huì)共享TCP連接和心跳信息。它們也可能共享數(shù)據(jù)集和數(shù)據(jù)結(jié)構(gòu),因此減少了每個(gè)任務(wù)的負(fù)載。
默認(rèn)情況下,如果subtask來(lái)自于不同的task,但來(lái)自于同一個(gè)job,F(xiàn)link允許這些subtask共享slot。這樣可能致使一個(gè)slot持有該job的整個(gè)pipeline。允許共享slot有兩個(gè)主要的好處:
- Flink集群需要許多slot來(lái)讓job達(dá)到最高的并行度,不用計(jì)算一個(gè)程序需要多少task。
- 更容易提高資源利用率。如果沒(méi)有slot共享,那些非密集型的任務(wù)(source、map)將會(huì)阻塞和密集的window subtask一樣多的資源。正是因?yàn)榱擞辛藄lot共享,可以提高2-6倍的并發(fā)度,同時(shí)仍然保證subtask之間合理的共享slot。
slot共享行為可以通過(guò)API控制,以防止不合理的共享,這個(gè)機(jī)制稱為 resource groups,它定義了哪些subtask可以共享的slot。
一個(gè)約定俗成的規(guī)則是,task slot推薦的默認(rèn)值是cpu的核數(shù)。對(duì)于超線程技術(shù),每個(gè)slot占用兩個(gè)或者更多的線程上下文。
3. 時(shí)間和窗口 Time and Window
聚合事件(例如count、sum)的工作在流計(jì)算上和批處理有些不同。流計(jì)算中,不可能一次性統(tǒng)計(jì)所有的元素并且返回統(tǒng)計(jì)結(jié)果;因?yàn)榱魍ǔJ菬o(wú)界的。取而代之的是,在流上做count/sum等聚合計(jì)算,可以限定window(窗口),例如統(tǒng)計(jì)最近5分鐘的數(shù)量,或?qū)ψ罱?00個(gè)元素求和。
窗口可以是時(shí)間驅(qū)動(dòng)的(比如,每30秒),也可以數(shù)據(jù)驅(qū)動(dòng)的(比如,每100個(gè)元素)。通常窗口可以區(qū)分為:tumbing windows(不重疊),sliding windows(有重疊)和session window(有空隙的活動(dòng))。
3.1 時(shí)間 Time
在流計(jì)算編程過(guò)程中,當(dāng)我們提到時(shí)間(Time),可能有不同的含義:
- Event Time 是事件的創(chuàng)建時(shí)間,通常用時(shí)間戳來(lái)描述,例如由傳感器或者生產(chǎn)服務(wù)來(lái)附加。Flink通過(guò)timestamp assigners訪問(wèn)事件時(shí)間。
- Ingestion Time 指事件從source operator進(jìn)入Flink dataflow的時(shí)間。
-
Processing Time 指執(zhí)行一個(gè)基于時(shí)間的操作的本地時(shí)間。
Paste_Image.png
更多關(guān)于處理時(shí)間的細(xì)節(jié),可以參考event time docs。
4. 狀態(tài)和容錯(cuò) State and Fault Tolerance
4.1 狀態(tài) State
在dataflow中的某一時(shí)刻,許多操作僅僅關(guān)注一個(gè)獨(dú)立的事件(例如一個(gè)事件解析器),有的操作能記住多個(gè)獨(dú)立的事件(例如window操作)。這些操作被成為是有狀態(tài)的(stateful)。
這些有狀態(tài)的操作的狀態(tài)是由一個(gè)可以被認(rèn)為是key/value的存儲(chǔ)維護(hù)的。這些狀態(tài)是分區(qū)和分布式的,和流一起被有狀態(tài)的操作(stateful operator)讀取。因此,訪問(wèn)key/value的狀態(tài)僅能在keyed Streams(執(zhí)行keyBy()函數(shù)之后產(chǎn)生)中進(jìn)行,并且只能通過(guò)當(dāng)前事件的key來(lái)訪問(wèn)其值。對(duì)齊stream的key和狀態(tài),可以確保所有狀態(tài)的更新都是本地操作,在不需要事務(wù)開(kāi)銷的情況下保證一致性。這個(gè)對(duì)齊也允許flink重新分步狀態(tài),并顯示的調(diào)整stream的分區(qū)。
4.2 檢查點(diǎn) Checkpoints for Fault Tolerance
Flink實(shí)現(xiàn)了失敗容忍機(jī)制,采用流重放(Stream replay)和檢查點(diǎn)(checkpoint)結(jié)合的方式。一個(gè)檢查點(diǎn)定義了流和狀態(tài)的一致點(diǎn),在該點(diǎn)streaming dataflow可以恢復(fù)并維持一致性(exactly-once的處理語(yǔ)義)。最新的檢查點(diǎn)之后的事件和狀態(tài)更新,將會(huì)在輸入流中重放。
4.3 狀態(tài)的存儲(chǔ) State Backends
為key/value構(gòu)建索引的數(shù)據(jù)結(jié)構(gòu)最終存儲(chǔ)的地方取決于存儲(chǔ)的選擇,可以是內(nèi)存中基于hash的map,也可以是RocksDB。為了定義持有狀態(tài)的數(shù)據(jù)結(jié)構(gòu),狀態(tài)的存儲(chǔ)也實(shí)現(xiàn)了基于時(shí)間點(diǎn)的快照機(jī)制,即對(duì)key/value的狀態(tài)做快照,并將快照作為檢查點(diǎn)的一部分來(lái)存儲(chǔ)。
5. 基于流的批處理 Batch on Streaming
Flink把批處理程序當(dāng)作一種特殊的流處理程序,把批處理看作是有界限的流(有限數(shù)量的元素)。一個(gè)DataSet在內(nèi)部被當(dāng)作是一個(gè)流。因此上面的這些適用于流處理的這些概念在批處理中同樣適用,只有很少的幾個(gè)例外:
DataSet API不適用檢查點(diǎn)。恢復(fù)機(jī)制是完整重放流數(shù)據(jù),這是合理的,因?yàn)檩斎氲臄?shù)據(jù)是有限的。它將開(kāi)銷更多的引入在恢復(fù)操作上,但另一方面也使得運(yùn)行時(shí)的常規(guī)流程的代價(jià)更低,因?yàn)樗苊饬藱z查點(diǎn)機(jī)制。
有狀態(tài)的操作使用了簡(jiǎn)單的in-memory/out-of-core的數(shù)據(jù)結(jié)構(gòu),而不是基于key/value的索引機(jī)制。
DataSet API引進(jìn)了獨(dú)特的同步迭代機(jī)制(superstep-based),僅限于用在有界的流。更多的內(nèi)容,可以查看這篇文檔iteration docs。
原文地址:https://ci.apache.org/projects/flink/flink-docs-release-1.1/concepts/concepts.html
(完)