概述:
Apache Flink是一個框架和分布式處理引擎荚坞,用于在無界和有界數(shù)據(jù)流上進(jìn)行有狀態(tài)計(jì)算。Flink被設(shè)計(jì)成可以在所有常見的集群環(huán)境中運(yùn)行收恢,以內(nèi)存速度和任何規(guī)模執(zhí)行計(jì)算兔港。
一.Flink體系結(jié)構(gòu)介紹
1.1 處理無界和有界數(shù)據(jù)
任何類型的數(shù)據(jù)都是作為事件流產(chǎn)生的。信用卡交易冠跷、傳感器測量、機(jī)器日志敢辩、網(wǎng)站或移動應(yīng)用程序上的用戶交互蔽莱,所有這些數(shù)據(jù)都以流的形式生成。
數(shù)據(jù)可以被處理為無邊界或有邊界的流戚长。
- 無邊界流有一個開始盗冷,但沒有定義結(jié)束。它們不會在生成數(shù)據(jù)時終止并提供數(shù)據(jù)同廉。不受限制的流必須被連續(xù)地處理仪糖,也就是說,事件必須在被攝取之后被迅速地處理迫肖。等待所有輸入數(shù)據(jù)到達(dá)是不可能的锅劝,因?yàn)檩斎胧菬o界的,在任何時間點(diǎn)都不會完成蟆湖。處理無界數(shù)據(jù)通常要求以特定的順序(例如事件發(fā)生的順序)攝取事件故爵,以便能夠推斷結(jié)果的完整性。
- 有界流有定義的開始和結(jié)束隅津。有界流可以通過在執(zhí)行任何計(jì)算之前獲取所有數(shù)據(jù)來處理诬垂。處理有界流不需要有序的輸入劲室,因?yàn)橛薪鐢?shù)據(jù)集總是可以排序的。有界流的處理也稱為批處理结窘。
Apache Flink擅長處理無界和有界數(shù)據(jù)集很洋。對時間和狀態(tài)的精確控制使Flink的運(yùn)行時能夠在無邊界流上運(yùn)行任何類型的應(yīng)用程序。有界流在內(nèi)部由專為固定大小的數(shù)據(jù)集設(shè)計(jì)的算法和數(shù)據(jù)結(jié)構(gòu)處理隧枫,產(chǎn)生卓越的性能喉磁。
1.2 部署應(yīng)用程序在任何地方
Apache Flink是一個分布式系統(tǒng),需要計(jì)算資源來執(zhí)行應(yīng)用程序官脓。Flink集成了所有常見的集群資源管理器协怒,如Hadoop YARN、Apache Mesos和Kubernetes卑笨,但也可以設(shè)置為作為獨(dú)立的集群運(yùn)行斤讥。
Flink被設(shè)計(jì)成能夠很好地工作于前面列出的每個資源管理器。這是通過特定于資源管理器的部署模式實(shí)現(xiàn)的湾趾,這種部署模式允許Flink以其慣用的方式與每個資源管理器交互。
在部署Flink應(yīng)用程序時派草,F(xiàn)link根據(jù)應(yīng)用程序配置的并行性自動識別所需的資源搀缠,并從資源管理器請求它們。在失敗的情況下近迁,F(xiàn)link通過請求新的資源來替換失敗的容器艺普。提交或控制應(yīng)用程序的所有通信都是通過REST調(diào)用進(jìn)行的。這簡化了Flink在許多環(huán)境中的集成鉴竭。
1.3 在任何規(guī)模上運(yùn)行應(yīng)用程序
Flink被設(shè)計(jì)為在任何規(guī)模上運(yùn)行有狀態(tài)流應(yīng)用程序歧譬。應(yīng)用程序被并行地分成數(shù)千個任務(wù),這些任務(wù)分布在一個集群中并并發(fā)地執(zhí)行搏存。因此瑰步,應(yīng)用程序可以利用幾乎不受限制的cpu、主內(nèi)存璧眠、磁盤和網(wǎng)絡(luò)IO缩焦。而且,F(xiàn)link可以輕松維護(hù)非常大的應(yīng)用程序狀態(tài)责静。它的異步和增量檢查點(diǎn)算法確保了對處理延遲的最小影響袁滥,同時保證了精確一次的狀態(tài)一致性。
用戶報(bào)告了在他們的生產(chǎn)環(huán)境中運(yùn)行的Flink應(yīng)用程序令人印象深刻的可伸縮性數(shù)字灾螃,例如:
- 應(yīng)用程序每天處理數(shù)萬億個事件题翻,
- 維護(hù)多個tb狀態(tài)的應(yīng)用程序
- 運(yùn)行在數(shù)千個內(nèi)核上的應(yīng)用程序。
1.4 利用內(nèi)存性能
有狀態(tài)Flink應(yīng)用程序?yàn)楸镜貭顟B(tài)訪問進(jìn)行了優(yōu)化腰鬼。任務(wù)狀態(tài)始終在內(nèi)存中維護(hù)嵌赠,如果狀態(tài)大小超過可用內(nèi)存塑荒,則在訪問效率高的磁盤數(shù)據(jù)結(jié)構(gòu)中維護(hù)。因此猾普,任務(wù)通過訪問本地(通常在內(nèi)存中)狀態(tài)來執(zhí)行所有計(jì)算袜炕,從而產(chǎn)生非常低的處理延遲。Flink通過定期和異步地將本地狀態(tài)檢查點(diǎn)指向持久存儲來保證故障時的精確一次狀態(tài)一致性初家。
二.應(yīng)用程序
2.1 流應(yīng)用程序的構(gòu)建塊
可以用流處理框架構(gòu)建和執(zhí)行的應(yīng)用程序類型由框架控制流偎窘、狀態(tài)和時間的程度來定義。在下面的文章中溜在,我們將描述流處理應(yīng)用程序的這些構(gòu)建塊陌知,并解釋Flink處理它們的方法。
流
顯然掖肋,流是流處理的一個基本方面仆葡。然而,流可以有不同的特征志笼,這些特征會影響流可以和應(yīng)該如何處理沿盅。Flink是一個通用的處理框架,可以處理任何類型的流纫溃。
有界和無界流:流可以是無界的腰涧,也可以是有界的,例如紊浩,固定大小的數(shù)據(jù)集窖铡。Flink具有處理無邊界流的復(fù)雜功能,但也有專門的操作符來有效地處理有邊界流坊谁。
實(shí)時記錄流:所有數(shù)據(jù)都以流的形式生成费彼。處理數(shù)據(jù)有兩種方法。在它生成時實(shí)時處理它口芍,或?qū)⒘鞒志没酱鎯ο到y(tǒng)箍铲,例如文件系統(tǒng)或?qū)ο蟠鎯Γ⒃谏院筇幚硭捉纭link應(yīng)用程序可以處理記錄的或?qū)崟r的流虹钮。
狀態(tài)
每個重要的流應(yīng)用程序都是有狀態(tài)的,也就是說膘融,只有對單個事件應(yīng)用轉(zhuǎn)換的應(yīng)用程序才不需要狀態(tài)芙粱。運(yùn)行基本業(yè)務(wù)邏輯的任何應(yīng)用程序都需要記住事件或中間結(jié)果,以便在以后的時間點(diǎn)訪問它們氧映,例如在接收到下一個事件時或在特定的持續(xù)時間之后春畔。
應(yīng)用狀態(tài)是Flink中的一等公民。您可以通過查看Flink在狀態(tài)處理上下文中提供的所有特性來了解這一點(diǎn)。
多個狀態(tài)原語:Flink為不同的數(shù)據(jù)結(jié)構(gòu)(如原子值律姨、列表或映射)提供狀態(tài)原語振峻。開發(fā)人員可以根據(jù)函數(shù)的訪問模式選擇最有效的狀態(tài)原語。
可插狀態(tài)后端:應(yīng)用狀態(tài)在可插狀態(tài)后端管理和檢查點(diǎn)择份。Flink具有不同的狀態(tài)后端扣孟,它們將狀態(tài)存儲在內(nèi)存或RocksDB中,RocksDB是一種高效的嵌入式磁盤數(shù)據(jù)存儲荣赶。也可以插入自定義狀態(tài)后端凤价。
精確一次狀態(tài)一致性:Flink的檢查點(diǎn)和恢復(fù)算法保證了應(yīng)用程序在出現(xiàn)故障時狀態(tài)的一致性。因此拔创,故障是透明處理的利诺,不會影響應(yīng)用程序的正確性。
非常大的狀態(tài):由于它的異步和增量檢查點(diǎn)算法剩燥,F(xiàn)link能夠維護(hù)數(shù)tb大小的應(yīng)用程序狀態(tài)慢逾。
可擴(kuò)展的應(yīng)用程序:Flink支持通過將狀態(tài)重新分配給更多或更少的工人來擴(kuò)展有狀態(tài)的應(yīng)用程序。
時間
時間是流媒體應(yīng)用程序的另一個重要組成部分灭红。大多數(shù)事件流都有固有的時間語義侣滩,因?yàn)槊總€事件都是在特定的時間點(diǎn)產(chǎn)生的。此外变擒,許多常見的流計(jì)算都是基于時間的胜卤,例如窗口聚合、會話化赁项、模式檢測和基于時間的連接。流處理的一個重要方面是應(yīng)用程序如何度量時間澈段,即事件時間和處理時間的差異悠菜。
Flink提供了一組豐富的時間相關(guān)特性。
事件時間模式:使用事件時間語義處理流的應(yīng)用程序根據(jù)事件的時間戳計(jì)算結(jié)果败富。因此悔醋,無論記錄的事件還是實(shí)時事件是被處理的,事件時間處理都能得到準(zhǔn)確和一致的結(jié)果兽叮。
水印支持:Flink在事件時間應(yīng)用中使用水印進(jìn)行時間推理芬骄。水印也是一種靈活的機(jī)制來權(quán)衡結(jié)果的延遲和完整性。
延遲數(shù)據(jù)處理:當(dāng)以事件-時間模式處理帶有水印的流時鹦聪,可能會發(fā)生在所有相關(guān)事件到達(dá)之前計(jì)算已經(jīng)完成账阻。這樣的事件被稱為晚事件。Flink提供了多個選項(xiàng)來處理后期事件泽本,比如通過端輸出重新路由事件和更新之前完成的結(jié)果淘太。
processing-time Mode:除了事件-時間模式外,F(xiàn)link還支持processing-time語義,即根據(jù)處理器的時鐘時間觸發(fā)計(jì)算蒲牧。處理時間模式適合某些嚴(yán)格要求低延遲撇贺、能夠容忍近似結(jié)果的應(yīng)用程序
2.2 分層的api
Flink提供了三層api。每種API都在簡潔性和表達(dá)性之間提供了不同的權(quán)衡冰抢,并針對不同的用例松嘶。
我們將簡要介紹每個API,討論它的應(yīng)用程序挎扰,并展示一個代碼示例翠订。
The ProcessFunctions
ProcessFunctions是Flink提供的最有表現(xiàn)力的函數(shù)接口。Flink提供ProcessFunctions來處理來自一個或兩個輸入流或在窗口中分組的事件的單個事件鼓鲁。ProcessFunctions提供對時間和狀態(tài)的細(xì)粒度控制蕴轨。ProcessFunction可以任意修改其狀態(tài),并注冊將來觸發(fā)回調(diào)函數(shù)的計(jì)時器骇吭。因此橙弱,ProcessFunctions可以實(shí)現(xiàn)許多有狀態(tài)事件驅(qū)動的應(yīng)用程序所需的復(fù)雜的每事件業(yè)務(wù)邏輯。
下面的示例顯示了一個KeyedProcessFunction燥狰,它操作KeyedStream并匹配START和END事件棘脐。當(dāng)接收到START事件時,該函數(shù)記住其狀態(tài)的時間戳龙致,并在4小時內(nèi)注冊一個計(jì)時器蛀缝。如果在定時器觸發(fā)之前收到一個END事件,函數(shù)計(jì)算END和START事件之間的持續(xù)時間目代,清除狀態(tài)并返回值屈梁。否則,計(jì)時器就會觸發(fā)并清除狀態(tài)榛了。
/**
* Matches keyed START and END events and computes the difference between
* both elements' timestamps. The first String field is the key attribute,
* the second String attribute marks START and END events.
*/
public static class StartEndDuration
extends KeyedProcessFunction<String, Tuple2<String, String>, Tuple2<String, Long>> {
private ValueState<Long> startTime;
@Override
public void open(Configuration conf) {
// obtain state handle
startTime = getRuntimeContext()
.getState(new ValueStateDescriptor<Long>("startTime", Long.class));
}
/** Called for each processed event. */
@Override
public void processElement(
Tuple2<String, String> in,
Context ctx,
Collector<Tuple2<String, Long>> out) throws Exception {
switch (in.f1) {
case "START":
// set the start time if we receive a start event.
startTime.update(ctx.timestamp());
// register a timer in four hours from the start event.
ctx.timerService()
.registerEventTimeTimer(ctx.timestamp() + 4 * 60 * 60 * 1000);
break;
case "END":
// emit the duration between start and end event
Long sTime = startTime.value();
if (sTime != null) {
out.collect(Tuple2.of(in.f0, ctx.timestamp() - sTime));
// clear the state
startTime.clear();
}
default:
// do nothing
}
}
/** Called when a timer fires. */
@Override
public void onTimer(
long timestamp,
OnTimerContext ctx,
Collector<Tuple2<String, Long>> out) {
// Timeout interval exceeded. Cleaning up the state.
startTime.clear();
}
}
該示例說明了KeyedProcessFunction的表達(dá)能力在讶,但也強(qiáng)調(diào)了它是一個相當(dāng)冗長的接口
The DataStream API
DataStream API為許多常見的流處理操作提供了原語,比如開窗霜大、一次記錄轉(zhuǎn)換构哺,以及通過查詢外部數(shù)據(jù)存儲來豐富事件。DataStream API可用于Java和Scala战坤,并基于map()曙强、reduce()和aggregate()等函數(shù)。函數(shù)可以通過擴(kuò)展接口定義途茫,也可以定義為Java或Scala lambda函數(shù)碟嘴。
下面的示例演示如何對點(diǎn)擊流進(jìn)行會話并計(jì)算每個會話的點(diǎn)擊次數(shù)。
// a stream of website clicks
DataStream<Click> clicks = ...
DataStream<Tuple2<String, Long>> result = clicks
// project clicks to userId and add a 1 for counting
.map(
// define function by implementing the MapFunction interface.
new MapFunction<Click, Tuple2<String, Long>>() {
@Override
public Tuple2<String, Long> map(Click click) {
return Tuple2.of(click.userId, 1L);
}
})
// key by userId (field 0)
.keyBy(0)
// define session window with 30 minute gap
.window(EventTimeSessionWindows.withGap(Time.minutes(30L)))
// count clicks per session. Define function as lambda function.
.reduce((a, b) -> Tuple2.of(a.f0, a.f1 + b.f1));
SQL & Table API
Flink具有兩個關(guān)系A(chǔ)PI, Table API和SQL囊卜。這兩個api都是批處理和流處理的統(tǒng)一api臀防,也就是說眠菇,查詢以相同的語義在無邊界的實(shí)時流或有邊界的記錄流上執(zhí)行,并產(chǎn)生相同的結(jié)果袱衷。Table API和SQL利用Apache Calcite進(jìn)行解析捎废、驗(yàn)證和查詢優(yōu)化。它們可以與DataStream和DataSet api無縫集成致燥,并支持用戶定義的標(biāo)量登疗、聚合和表值函數(shù)。
Flink的關(guān)系api旨在簡化數(shù)據(jù)分析嫌蚤、數(shù)據(jù)管道和ETL應(yīng)用程序的定義辐益。
下面的示例顯示了會話化單擊流并計(jì)算每個會話的單擊次數(shù)的SQL查詢。這與DataStream API示例中的用例相同脱吱。
SELECT userId, COUNT(*)
FROM clicks
GROUP BY SESSION(clicktime, INTERVAL '30' MINUTE), userId
2.3 庫
Flink為常見的數(shù)據(jù)處理用例提供了幾個庫智政。這些庫通常嵌入到API中,并不是完全自包含的箱蝠。因此续捂,它們可以從API的所有特性中受益,并與其他庫集成宦搬。
復(fù)雜事件處理(CEP):模式檢測是事件流處理的一個非常常見的用例牙瓢。Flink的CEP庫提供了一個API來指定事件模式(可以考慮正則表達(dá)式或狀態(tài)機(jī))。CEP庫與Flink的DataStream API集成在一起间校,這樣就可以在DataStreams上評估模式矾克。CEP庫的應(yīng)用程序包括網(wǎng)絡(luò)入侵檢測、業(yè)務(wù)流程監(jiān)控和欺詐檢測憔足。
DataSet API: DataSet API是Flink用于批處理應(yīng)用程序的核心API胁附。DataSet API的原語包括map、reduce滓彰、(外部)連接汉嗽、co-group和iterate。所有操作都由算法和數(shù)據(jù)結(jié)構(gòu)支持找蜜,這些算法和數(shù)據(jù)結(jié)構(gòu)對內(nèi)存中的序列化數(shù)據(jù)進(jìn)行操作,如果數(shù)據(jù)大小超過內(nèi)存預(yù)算稳析,就會溢出到磁盤洗做。Flink的DataSet API的數(shù)據(jù)處理算法受到了傳統(tǒng)數(shù)據(jù)庫操作符的啟發(fā),比如混合散列連接或外部合并排序彰居。
Gelly: Gelly是一個用于可伸縮圖形處理和分析的庫诚纸。Gelly是在DataSet API之上實(shí)現(xiàn)并與之集成的。因此陈惰,它得益于其可擴(kuò)展和健壯的操作符畦徘。Gelly提供了內(nèi)置算法,如標(biāo)簽傳播、三角形枚舉和頁面排名井辆,但還提供了一個Graph API关筒,可以簡化自定義圖算法的實(shí)現(xiàn)。
三. 操作
3.1 7*24 不間斷運(yùn)行應(yīng)用程序
機(jī)器和進(jìn)程故障在分布式系統(tǒng)中是普遍存在的杯缺。像Flink這樣的分布式流處理器必須從故障中恢復(fù)蒸播,才能全天候運(yùn)行流應(yīng)用程序。顯然萍肆,這不僅意味著在故障后重新啟動應(yīng)用程序袍榆,而且還意味著確保其內(nèi)部狀態(tài)保持一致,以便應(yīng)用程序可以繼續(xù)處理塘揣,就像故障從未發(fā)生過一樣包雀。
Flink提供了幾個特性,以確保應(yīng)用程序保持運(yùn)行和保持一致:
一致的檢查點(diǎn):Flink的恢復(fù)機(jī)制基于應(yīng)用程序狀態(tài)的一致檢查點(diǎn)亲铡。如果出現(xiàn)故障才写,則重新啟動應(yīng)用程序,并從最新的檢查點(diǎn)加載其狀態(tài)奴愉。結(jié)合可重置的流源琅摩,該特性可以保證精確一次的狀態(tài)一致性。
高效的檢查點(diǎn):如果應(yīng)用程序維護(hù)著tb級的狀態(tài)锭硼,那么檢查點(diǎn)應(yīng)用程序的狀態(tài)是非常昂貴的房资。Flink可以執(zhí)行異步和增量檢查點(diǎn),以保持檢查點(diǎn)對應(yīng)用程序延遲sla的影響非常小檀头。
端到端只寫一次:Flink為特定的存儲系統(tǒng)提供了事務(wù)接收功能轰异,保證數(shù)據(jù)只寫一次,即使發(fā)生故障暑始。
與集群管理器集成:Flink與集群管理器緊密集成搭独,如Hadoop YARN、Mesos或Kubernetes廊镜。當(dāng)一個流程失敗時牙肝,會自動啟動一個新的流程來接管它的工作。
高可用性設(shè)置:Flink具有高可用性模式嗤朴,消除了所有單點(diǎn)故障配椭。ha模式基于Apache ZooKeeper,這是一個經(jīng)過實(shí)戰(zhàn)驗(yàn)證的可靠的分布式協(xié)調(diào)服務(wù)雹姊。
3.2 更新股缸、遷移、掛起和恢復(fù)應(yīng)用程序
支持關(guān)鍵業(yè)務(wù)服務(wù)的流應(yīng)用程序需要維護(hù)吱雏。漏洞需要修復(fù)敦姻,改進(jìn)或新功能需要實(shí)現(xiàn)瘾境。然而,更新有狀態(tài)流應(yīng)用程序并非易事镰惦。通常不能簡單地停止應(yīng)用程序并重新啟動一個固定的或改進(jìn)的版本迷守,因?yàn)椴荒苁?yīng)用程序的狀態(tài)。
Flink的Savepoints是一個獨(dú)特而強(qiáng)大的特性陨献,它解決了更新有狀態(tài)應(yīng)用程序和許多其他相關(guān)挑戰(zhàn)的問題盒犹。保存點(diǎn)是應(yīng)用程序狀態(tài)的一致快照,因此非常類似于檢查點(diǎn)眨业。然而急膀,與檢查點(diǎn)不同的是,保存點(diǎn)需要手動觸發(fā)龄捡,并且在應(yīng)用程序停止時不會自動刪除卓嫂。保存點(diǎn)可用于啟動與狀態(tài)兼容的應(yīng)用程序并初始化其狀態(tài)。保存點(diǎn)啟用以下功能:
應(yīng)用程序演進(jìn):保存點(diǎn)可用于演進(jìn)應(yīng)用程序聘殖。應(yīng)用程序的固定版本或改進(jìn)版本可以從取自該應(yīng)用程序以前版本的保存點(diǎn)重新啟動晨雳。也可以從較早的時間點(diǎn)(假設(shè)存在這樣的保存點(diǎn))啟動應(yīng)用程序,以修復(fù)由有缺陷的版本產(chǎn)生的不正確結(jié)果奸腺。
集群遷移:使用保存點(diǎn)餐禁,可以將應(yīng)用程序遷移(或克隆)到不同的集群。
Flink版本更新:可以使用保存點(diǎn)將應(yīng)用程序遷移到新的Flink版本上運(yùn)行突照。
應(yīng)用程序擴(kuò)展:保存點(diǎn)可以用來增加或減少應(yīng)用程序的并行度帮非。
A/B測試和假設(shè)場景:一個應(yīng)用程序的兩個(或更多)不同版本的性能或質(zhì)量可以通過從同一個保存點(diǎn)啟動所有版本來進(jìn)行比較。
暫停和恢復(fù):可以通過獲取保存點(diǎn)并停止它來暫停應(yīng)用程序讹蘑。在以后的任何時間點(diǎn)末盔,應(yīng)用程序都可以從保存點(diǎn)恢復(fù)。
存檔:可以對保存點(diǎn)進(jìn)行存檔座慰,以便能夠?qū)?yīng)用程序的狀態(tài)重置為更早的時間點(diǎn)
3.3 監(jiān)控您的應(yīng)用程序
就像任何其他服務(wù)一樣陨舱,持續(xù)運(yùn)行的流應(yīng)用程序需要被監(jiān)督并集成到運(yùn)營基礎(chǔ)設(shè)施中,即組織的監(jiān)視和日志服務(wù)版仔。監(jiān)控有助于預(yù)測問題并提前做出反應(yīng)游盲。日志記錄使根源分析能夠調(diào)查失敗。最后蛮粮,控制正在運(yùn)行的應(yīng)用程序的易于訪問的接口是一個重要特性益缎。
Flink很好地集成了許多常見的日志和監(jiān)視服務(wù),并提供了一個REST API來控制應(yīng)用程序和查詢信息蝉揍。
Web UI: Flink提供Web UI,用于檢查畦娄、監(jiān)控和調(diào)試運(yùn)行中的應(yīng)用程序又沾。它還可以用于提交執(zhí)行或取消執(zhí)行弊仪。
日志:Flink實(shí)現(xiàn)了流行的slf4j日志接口,并與日志框架log4j或logback集成杖刷。
度量:Flink提供了一個復(fù)雜的度量系統(tǒng)來收集和報(bào)告系統(tǒng)和用戶定義的度量励饵。指標(biāo)可以導(dǎo)出到多個記者,包括JMX滑燃、Ganglia役听、Graphite、Prometheus表窘、StatsD典予、Datadog和Slf4j。
REST API: Flink公開REST API以提交新應(yīng)用程序乐严、獲取運(yùn)行應(yīng)用程序的保存點(diǎn)或取消應(yīng)用程序瘤袖。REST API還公開元數(shù)據(jù)和收集的運(yùn)行或完成應(yīng)用程序的指標(biāo)。