Flink定義
Apache Flink is a framework and distributed processing engine for stateful computations over unbounded and bounded data streams.
Apache Flink 是一個(gè)框架和分布式處理引擎橙凳,用于對(duì)無(wú)界和有界數(shù)據(jù)流進(jìn)行狀態(tài)計(jì)算呕缭。
Flink相關(guān)概念
批處理是有界數(shù)據(jù)流處理的范例牵囤。在這種模式下侯繁,你可以選擇在計(jì)算結(jié)果輸出之前輸入整個(gè)數(shù)據(jù)集,這也就意味著你可以對(duì)整個(gè)數(shù)據(jù)集的數(shù)據(jù)進(jìn)行排序廷臼、統(tǒng)計(jì)或匯總計(jì)算后再輸出結(jié)果俯在。
流處理正相反杆烁,其涉及無(wú)界數(shù)據(jù)流。至少理論上來(lái)說(shuō)禽翼,它的數(shù)據(jù)輸入永遠(yuǎn)不會(huì)結(jié)束屠橄,因此程序必須持續(xù)不斷地對(duì)到達(dá)的數(shù)據(jù)進(jìn)行處理萨惑。
Flink架構(gòu)
在Flink中執(zhí)行應(yīng)用程序主要涉及三個(gè)實(shí)體:Client,JobManager和TaskManagers仇矾。
Client
client不是運(yùn)行時(shí)和程序執(zhí)行的一部分庸蔼,而是用于準(zhǔn)備數(shù)據(jù)流并將其發(fā)送給 JobManager。之后贮匕,客戶端可以斷開(kāi)連接(分離模式)姐仅,或保持連接來(lái)接收進(jìn)程報(bào)告(附加模式)
JobManager
控制一個(gè)應(yīng)用程序執(zhí)行的主進(jìn)程,也就是說(shuō)刻盐,每個(gè)應(yīng)用程序都會(huì)被一個(gè)不同的JobManager 所控制執(zhí)行掏膏。
JobManager 會(huì)先接收到要執(zhí)行的應(yīng)用程序,這個(gè)應(yīng)用程序會(huì)包括:作業(yè)圖(JobGraph)敦锌、邏輯數(shù)據(jù)流圖(logical dataflow graph)和打包了所有的類馒疹、庫(kù)和其它資源的JAR包。
JobManager 會(huì)把JobGraph轉(zhuǎn)換成一個(gè)物理層面的數(shù)據(jù)流圖乙墙,這個(gè)圖被叫做“執(zhí)行圖”(ExecutionGraph)颖变,包含了所有可以并發(fā)執(zhí)行的任務(wù)。
JobManager 會(huì)向資源管理器(ResourceManager)請(qǐng)求執(zhí)行任務(wù)必要的資源听想,也就是任務(wù)管理器(TaskManager)上的插槽(slot)腥刹。一旦它獲取到了足夠的資源,就會(huì)將執(zhí)行圖分發(fā)到真正運(yùn)行它們的TaskManager上汉买。而在運(yùn)行過(guò)程中衔峰,JobManager會(huì)負(fù)責(zé)所有需要中央?yún)f(xié)調(diào)的操作,比如說(shuō)檢查點(diǎn)(checkpoints)的協(xié)調(diào)蛙粘。
ResourceManager
主要負(fù)責(zé)管理任務(wù)管理器(TaskManager)的插槽(slot)垫卤,TaskManger 插槽是Flink中定義的處理資源單元。
Flink為不同的環(huán)境和資源管理工具提供了不同資源管理器出牧,比如YARN穴肘、Mesos、K8s崔列,以及standalone部署梢褐。
當(dāng)JobManager申請(qǐng)插槽資源時(shí),ResourceManager會(huì)將有空閑插槽的TaskManager分配給JobManager赵讯。如果ResourceManager沒(méi)有足夠的插槽來(lái)滿足JobManager的請(qǐng)求盈咳,它還可以向資源提供平臺(tái)發(fā)起會(huì)話,以提供啟動(dòng)TaskManager進(jìn)程的容器边翼。
Dispatcher
可以跨作業(yè)運(yùn)行鱼响,它為應(yīng)用提交提供了REST接口。
當(dāng)一個(gè)應(yīng)用被提交執(zhí)行時(shí)组底,分發(fā)器就會(huì)啟動(dòng)并將應(yīng)用移交給一個(gè)JobManager丈积。
Dispatcher也會(huì)啟動(dòng)一個(gè)Web UI筐骇,用來(lái)方便地展示和監(jiān)控作業(yè)執(zhí)行的信息。
Dispatcher在架構(gòu)中可能并不是必需的江滨,這取決于應(yīng)用提交運(yùn)行的方式铛纬。
JobMaster
JobMaster負(fù)責(zé)管理單個(gè)JobGraph的執(zhí)行。Flink 集群中可以同時(shí)運(yùn)行多個(gè)作業(yè)唬滑,每個(gè)作業(yè)都有自己的 JobMaster告唆。
TaskManager
Flink中的工作進(jìn)程。通常在Flink中會(huì)有多個(gè)TaskManager運(yùn)行晶密,每一個(gè)TaskManager都包含了一定數(shù)量的插槽(slots)擒悬。插槽的數(shù)量限制了TaskManager能夠執(zhí)行的任務(wù)數(shù)量。
啟動(dòng)之后稻艰,TaskManager會(huì)向資源管理器注冊(cè)它的插槽懂牧;收到資源管理器的指令后,TaskManager就會(huì)將一個(gè)或者多個(gè)插槽提供給JobManager調(diào)用尊勿。JobManager就可以向插槽分配任務(wù)(tasks)來(lái)執(zhí)行了僧凤。
在執(zhí)行過(guò)程中,一個(gè)TaskManager可以跟其它運(yùn)行同一應(yīng)用程序的TaskManager交換數(shù)據(jù)运怖。
時(shí)間語(yǔ)義
Flink 明確支持以下三種時(shí)間語(yǔ)義:
事件時(shí)間(event time): 事件產(chǎn)生的時(shí)間拼弃,記錄的是設(shè)備生產(chǎn)(或者存儲(chǔ))事件的時(shí)間
攝取時(shí)間(ingestion time): Flink 讀取事件時(shí)記錄的時(shí)間
處理時(shí)間(processing time): Flink pipeline 中具體算子處理事件的時(shí)間
在 Flink 的流式處理中夏伊,絕大部分的業(yè)務(wù)都會(huì)使用 eventTime摇展。
我們知道,流處理從事件產(chǎn)生溺忧,到流經(jīng) source咏连,再到 operator,中間是有一個(gè)過(guò)程和時(shí)間的鲁森,雖然大部分情況下祟滴,流到 operator 的數(shù)據(jù)都是按照事件產(chǎn)生的時(shí)間順序來(lái)的,但是也不排除由于網(wǎng)絡(luò)歌溉、分布式等原因垄懂,導(dǎo)致亂序的產(chǎn)生,所謂亂序痛垛,就是指 Flink 接收到的事件的先后順序不是嚴(yán)格按照事件的 Event Time 順序排列的草慧。
window
出現(xiàn)亂序數(shù)據(jù),首先想到的是要排序匙头,但是流式數(shù)據(jù)中不能等待所有數(shù)據(jù)都到達(dá)再進(jìn)行排序漫谷,而是要將數(shù)據(jù)流切分為數(shù)據(jù)集,并對(duì)數(shù)據(jù)集進(jìn)行排序蹂析,由此引入窗口的概念舔示。 窗口是一種切割無(wú)限數(shù)據(jù)為有限塊進(jìn)行處理的手段碟婆,是無(wú)限數(shù)據(jù)流處理的核心。
Flink 有一些內(nèi)置的窗口分配器惕稻,如下所示:
可以對(duì)窗口內(nèi)收集到的數(shù)據(jù)做聚合或者其他處理操作竖共,主要非為兩大類:
增量聚合函數(shù)(incremental aggregation functions):每條數(shù)據(jù)到來(lái)就進(jìn)行計(jì)算,保持一個(gè)簡(jiǎn)單的狀態(tài)俺祠。
全窗口函數(shù)(full window functions):先把窗口所有數(shù)據(jù)收集起來(lái)肘迎,等到計(jì)算的時(shí)候會(huì)遍歷所有數(shù)據(jù)。
Flink提供了豐富的window API:
Watermark
窗口操作雖然可以解決亂序問(wèn)題锻煌,但是依然存在遲到數(shù)據(jù)的現(xiàn)象妓布,由此引入Watermark。
當(dāng)一個(gè)窗口戳到了關(guān)閉時(shí)間宋梧,不應(yīng)該立刻觸發(fā)窗口計(jì)算匣沼,而是等待一段時(shí)間,等遲到的數(shù)據(jù)來(lái)了再關(guān)閉窗口捂龄。數(shù)據(jù)流中的 Watermark 用于表示 timestamp 小于 Watermark 的數(shù)據(jù)都已經(jīng)到達(dá)了释涛,因此,window 的執(zhí)行也是由 Watermark 觸發(fā)的倦沧。
watermarks 給了開(kāi)發(fā)人員一種選擇唇撬,使開(kāi)發(fā)者做流處理時(shí)可以控制延遲和結(jié)果正確性之間的權(quán)衡。
如果watermark設(shè)置的延遲太大展融,收到結(jié)果的速度可能就會(huì)很慢窖认,解決辦法是在水位線到達(dá)之前輸出一個(gè)近似結(jié)果(增量聚合)。
如果watermark到達(dá)得太小告希,則可能收到錯(cuò)誤結(jié)果扑浸,不過(guò) Flink 可以通過(guò)側(cè)輸出流、允許的延遲(allowed lateness)的間隔解決這個(gè)問(wèn)題燕偶。
State Backends
由于有效的狀態(tài)訪問(wèn)對(duì)于處理數(shù)據(jù)的低延遲至關(guān)重要喝噪,因此每個(gè)并行任務(wù)都會(huì)在本地維護(hù)其狀態(tài),以確敝该矗快速的狀態(tài)訪問(wèn)酝惧。每傳入一條數(shù)據(jù),有狀態(tài)的算子任務(wù)都會(huì)讀取和更新?tīng)顟B(tài)伯诬。狀態(tài)的存儲(chǔ)晚唇、訪問(wèn)以及維護(hù),由一個(gè)可插入的組件決定姑廉,這個(gè)組件就叫做狀態(tài)后端(state backend) 缺亮。如果發(fā)生故障,F(xiàn)link 可以恢復(fù)應(yīng)用程序的完整狀態(tài)并繼續(xù)處理。
狀態(tài)后端主要負(fù)責(zé)兩件事:本地的狀態(tài)管理萌踱,以及將檢查點(diǎn)(checkpoint)狀態(tài)寫入遠(yuǎn)程存儲(chǔ)葵礼。
名稱 | 狀態(tài)存儲(chǔ)位置 | checkpoint存儲(chǔ)位置 | 快照 | 特點(diǎn) |
---|---|---|---|---|
RocksDBStateBackend | RocksDB | RocksDB | 全量 / 增量 | 支持大于內(nèi)存大小的狀態(tài)經(jīng)驗(yàn)法則:比基于堆的后端慢10倍 |
FsStateBackend | TM JVM Heap | 分布式文件系統(tǒng) | 全量 | 快速,需要大的堆內(nèi)存受限制于 GC 同時(shí)擁有內(nèi)存級(jí)的本地訪問(wèn)速度并鸵,和更好的容錯(cuò)保證 |
MemoryStateBackend | TM JVM Heap | JM JVM Heap | 全量 | 適用于小狀態(tài)(本地)的測(cè)試和實(shí)驗(yàn) 快速鸳粉、低延遲,但不穩(wěn)定 |
算子狀態(tài)的作用范圍限定為算子任務(wù)园担,由同一并行任務(wù)所處理的所有數(shù)據(jù)都可以訪問(wèn)到相同的狀態(tài)届谈,如聚合每分鐘的事件時(shí),可將一分鐘內(nèi)數(shù)據(jù)的增量聚合結(jié)果作為狀態(tài)保存弯汰。
Checkpoint
Checkpoint是由 Flink 自動(dòng)執(zhí)行的快照艰山,F(xiàn)link 故障恢復(fù)機(jī)制的核心就是應(yīng)用狀態(tài)的一致性檢查點(diǎn)。有狀態(tài)流應(yīng)用的一致檢查點(diǎn)咏闪,其實(shí)就是所有任務(wù)的狀態(tài)曙搬,在某個(gè)時(shí)間點(diǎn)的一份拷貝(一份快照),這個(gè)時(shí)間點(diǎn)鸽嫂,應(yīng)該是所有任務(wù)都恰好處理完一個(gè)相同的輸入數(shù)據(jù)的時(shí)候纵装。
在執(zhí)行流應(yīng)用程序期間,F(xiàn)link 會(huì)定期保存狀態(tài)的一致檢查點(diǎn)据某。如果發(fā)生故障橡娄, Flink 將會(huì)使用最近的檢查點(diǎn)來(lái)一致恢復(fù)應(yīng)用程序的狀態(tài),并重新啟動(dòng)處理流程
遇到故障之后癣籽,第一步就是重啟應(yīng)用
第二步是從 checkpoint 中讀取狀態(tài)挽唉,將狀態(tài)重置。從檢查點(diǎn)重新啟動(dòng)應(yīng)用程序后才避,其內(nèi)部狀態(tài)與檢查點(diǎn)完成時(shí)的狀態(tài)完全相同
第三步:開(kāi)始消費(fèi)并處理檢查點(diǎn)到發(fā)生故障之間的所有數(shù)據(jù)橱夭,這種檢查點(diǎn)的保存和恢復(fù)機(jī)制可以為應(yīng)用程序狀態(tài)提供“精確一次”(exactly-once)的一致性,因?yàn)樗兴阕佣紩?huì)保存檢查點(diǎn)并恢復(fù)其所有狀態(tài)桑逝,這樣一來(lái)所有的輸入流就都會(huì)被重置到檢查點(diǎn)完成時(shí)的位置。
Savepoint
一個(gè) Savepoint俏让,就是一個(gè)應(yīng)用服務(wù)狀態(tài)的一致性快照楞遏,因此其與checkpoint組件的很相似,但是與checkpoint相比首昔,Savepoint 需要手動(dòng)觸發(fā)啟動(dòng)寡喝,而且當(dāng)流應(yīng)用服務(wù)停止時(shí),它并不會(huì)自動(dòng)刪除勒奇。Savepoint 常被應(yīng)用于啟動(dòng)一個(gè)已含有狀態(tài)的流服務(wù)预鬓,并初始化其(備份時(shí))狀態(tài)。
Savepoint 有以下特點(diǎn):
便于升級(jí)應(yīng)用服務(wù)版本: Savepoint 常在應(yīng)用版本升級(jí)時(shí)使用赊颠,當(dāng)前應(yīng)用的新版本更新升級(jí)時(shí)格二,可以根據(jù)上一個(gè)版本程序記錄的 Savepoint 內(nèi)的服務(wù)狀態(tài)信息來(lái)重啟服務(wù)劈彪。它也可能會(huì)使用更早的 Savepoint 還原點(diǎn)來(lái)重啟服務(wù),以便于修復(fù)由于有缺陷的程序版本導(dǎo)致的不正確的程序運(yùn)行結(jié)果顶猜。
方便集群服務(wù)移植: 通過(guò)使用 Savepoint沧奴,流服務(wù)應(yīng)用可以自由的在不同集群中遷移部署。
方便Flink版本升級(jí): 通過(guò)使用 Savepoint长窄,可以使應(yīng)用服務(wù)在升級(jí)Flink時(shí)滔吠,更加安全便捷。
增加應(yīng)用并行服務(wù)的擴(kuò)展性: Savepoint 也常在增加或減少應(yīng)用服務(wù)集群的并行度時(shí)使用挠日。
便于A/B測(cè)試及假設(shè)分析場(chǎng)景對(duì)比結(jié)果: 通過(guò)把同一應(yīng)用在使用不同版本的應(yīng)用程序疮绷,基于同一個(gè) Savepoint 還原點(diǎn)啟動(dòng)服務(wù)時(shí),可以測(cè)試對(duì)比2個(gè)或多個(gè)版本程序的性能及服務(wù)質(zhì)量嚣潜。
暫停和恢復(fù)服務(wù): 一個(gè)應(yīng)用服務(wù)可以在新建一個(gè) Savepoint 后再停止服務(wù)矗愧,以便于后面任何時(shí)間點(diǎn)再根據(jù)這個(gè)實(shí)時(shí)刷新的 Savepoint 還原點(diǎn)進(jìn)行恢復(fù)服務(wù)。
歸檔服務(wù): Savepoint 還提供還原點(diǎn)的歸檔服務(wù)郑原,以便于用戶能夠指定時(shí)間點(diǎn)的 Savepoint 的服務(wù)數(shù)據(jù)進(jìn)行重置應(yīng)用服務(wù)的狀態(tài)唉韭,進(jìn)行恢復(fù)服務(wù)。
狀態(tài)一致性
AT-MOST-ONCE(最多一次)
AT-LEAST-ONCE(至少一次)
EXACTLY-ONCE(精確一次)
Flink內(nèi)部的狀態(tài)一致性
Flink 使用了一種輕量級(jí)快照機(jī)制 —— 檢查點(diǎn)(checkpoint)來(lái)保證 exactly-once 語(yǔ)義
端到端的狀態(tài)一致性
流處理應(yīng)用除了流處理器以外還包含了數(shù)據(jù)源(例如 Kafka)和輸出到持久化系統(tǒng)犯犁。端到端的一致性保證属愤,意味著結(jié)果的正確性貫穿了整個(gè)流處理應(yīng)用的始終;每一個(gè)組件都保證了它自己的一致性酸役。整個(gè)端到端的一致性級(jí)別取決于所有組件中一致性最弱的組件住诸。
內(nèi)部保證 —— checkpoint
source 端 —— 可重設(shè)數(shù)據(jù)的讀取位置(kafka可以設(shè)置讀取的offset)
sink 端 —— 從故障恢復(fù)時(shí),數(shù)據(jù)不會(huì)重復(fù)寫入外部系統(tǒng)
為實(shí)現(xiàn)目標(biāo)端數(shù)據(jù)不重復(fù)下寫入有以下實(shí)現(xiàn)方式:
冪等寫入:(僅在目標(biāo)端表有主鍵的情況下適用)
事務(wù)寫入:構(gòu)建的事務(wù)對(duì)應(yīng)著 checkpoint涣澡,等到 checkpoint 真正完成的時(shí)候贱呐,才把所有對(duì)應(yīng)的結(jié)果寫入 sink 系統(tǒng)中。
事務(wù)寫入的兩種實(shí)現(xiàn)方式:
預(yù)寫日志 (GenericWriteAheadSink)
兩階段提交(TwoPhaseCommitSinkFunction )
預(yù)寫日志:
把結(jié)果數(shù)據(jù)先當(dāng)成狀態(tài)保存入桂,然后在收到 checkpoint 完成的通知時(shí)奄薇,一次性寫入 sink 系統(tǒng)。
簡(jiǎn)單易于實(shí)現(xiàn)抗愁,由于數(shù)據(jù)提前在狀態(tài)后端中做了緩存馁蒂,所以無(wú)論什么sink 系統(tǒng),都能用這種方式一批搞定蜘腌。
缺點(diǎn):微批處理沫屡,不能保證一批數(shù)據(jù)全部成功。
兩階段提交:
對(duì)于每個(gè) checkpoint撮珠,sink 任務(wù)會(huì)啟動(dòng)一個(gè)事務(wù)沮脖,并將接下來(lái)所有接收的數(shù)據(jù)添加到事務(wù)里。
然后將這些數(shù)據(jù)寫入外部 sink 系統(tǒng),但不提交它們 —— 這時(shí)只是“預(yù)提交”勺届。
當(dāng)它收到 checkpoint 完成的通知時(shí)驶俊,它才正式提交事務(wù),實(shí)現(xiàn)結(jié)果的真正寫入涮因。
2PC 對(duì)外部 sink 系統(tǒng)的要求
外部 sink 系統(tǒng)必須提供事務(wù)支持废睦,或者 sink 任務(wù)必須能夠模擬外部系統(tǒng)上的事務(wù)。
在 checkpoint 的間隔期間里养泡,必須能夠開(kāi)啟一個(gè)事務(wù)并接受數(shù)據(jù)寫入嗜湃。
在收到 checkpoint 完成的通知之前,事務(wù)必須是“等待提交”的狀態(tài)澜掩。 在故障恢復(fù)的情況下购披,這可能需要一些時(shí)間。如果這個(gè)時(shí)候sink系統(tǒng)關(guān)閉事務(wù)(例如超時(shí)了)肩榕,那么未提交的數(shù)據(jù)就會(huì)丟失刚陡。
sink 任務(wù)必須能夠在進(jìn)程失敗后恢復(fù)事務(wù)。
提交事務(wù)必須是冪等操作株汉。
部署
部署模式
Application Mode
Per-Job Mode
Session Mode
client load:此過(guò)程包括在本地下載應(yīng)用程序的依賴項(xiàng)筐乳,執(zhí)行用戶代碼以提取 Flink 的運(yùn)行時(shí)可以理解的應(yīng)用程序(即JobGraph
),并將依賴項(xiàng)和JobGraph(s)
傳送到集群乔妈。
部署模式 | client load執(zhí)行位置 | JM是否隔離 | TM是否隔離 | 原生k8s集群是否支持 |
---|---|---|---|---|
Application Mode | Client | 是 | 是 | 是 |
Per-Job Mode | JM | 是 | 是 | 否 |
Session Mode | JM | 否 | 否 | 是 |
Flink對(duì)k8s集群的要求
Kubernetes版本大于等于1.9蝙云。
可以訪問(wèn)列表,創(chuàng)建路召,刪除容器和服務(wù)勃刨,可以通過(guò)進(jìn)行配置
~/.kube/config
。您可以通過(guò)運(yùn)行來(lái)驗(yàn)證權(quán)限kubectl auth can-i <list|create|edit|delete> pods
股淡。啟用Kubernetes DNS身隐。
RBAC:d
efault service account
具有創(chuàng)建,刪除Pod的權(quán)限唯灵。
關(guān)注作者公眾號(hào) HEY DATA贾铝,一起討論更多