Flink 1.13,面向流批一体的运行时与 DataStream API 优化
本文由社區(qū)志愿者苗文婷整理,內(nèi)容來(lái)源自阿里巴巴技術(shù)專(zhuān)家高赟(云騫) 在 5 月 22 日北京站 Flink Meetup 分享的《面向流批一體的 Flink 運(yùn)行時(shí)與 DataStream API 優(yōu)化》。文章主要分為 4 個(gè)部分:
GitHub 地址
https://github.com/apache/flink
歡迎大家給 Flink 點(diǎn)贊送 star~
1. 流批一體的 Flink
1.1 架構(gòu)介紹
首先看下 Flink 流批一體的整體邏輯。Flink 在早期的時(shí)候,雖然是一個(gè)可以同時(shí)支持流處理和批處理的框架,但是它的流處理和批處理的實(shí)現(xiàn),不管是在 API 層,還是在底下的 Shuffle、調(diào)度、算子層,都是單獨(dú)的兩套。這兩套實(shí)現(xiàn)是完全獨(dú)立的,沒(méi)有特別緊密的關(guān)聯(lián)。
在流批一體這一目標(biāo)的引導(dǎo)下,Flink 現(xiàn)在已經(jīng)對(duì)底層的算子、調(diào)度、Shuffle 進(jìn)行了統(tǒng)一的抽象,以統(tǒng)一的方式向上支持 DataStream API 和 Table API 兩套接口。DataStream API 是一種比較偏物理層的接口,Table API 是一種 Declearetive 的接口,這兩套接口對(duì)流和批來(lái)說(shuō)都是統(tǒng)一的。
1.2 優(yōu)點(diǎn)
- 代碼復(fù)用
基于 DataStream API 和 Table API,用戶(hù)可以寫(xiě)同一套代碼來(lái)同時(shí)處理歷史的數(shù)據(jù)和實(shí)時(shí)的數(shù)據(jù),例如數(shù)據(jù)回流的場(chǎng)景。
- 易于開(kāi)發(fā)
統(tǒng)一的 Connector 和算子實(shí)現(xiàn),減少開(kāi)發(fā)和維護(hù)的成本。
- 易于學(xué)習(xí)
減少學(xué)習(xí)成本,避免學(xué)習(xí)兩套相似接口。
- 易于維護(hù)
使用同一系統(tǒng)支持流作業(yè)和批作業(yè),減少維護(hù)成本。
1.3 數(shù)據(jù)處理過(guò)程
下面簡(jiǎn)單介紹 Flink 是怎么抽象流批一體的,Flink 把作業(yè)拆成了兩種:
- 第一種類(lèi)型的作業(yè)是處理無(wú)限數(shù)據(jù)的無(wú)限流的作業(yè)
這種作業(yè)就是我們平時(shí)所認(rèn)知的流作業(yè),對(duì)于這種作業(yè),Flink 采用一個(gè)標(biāo)準(zhǔn)流的執(zhí)行模式,需要考慮記錄的時(shí)間,通過(guò) Watermark 對(duì)齊的方式推進(jìn)整個(gè)系統(tǒng)的時(shí)間以達(dá)到一些數(shù)據(jù)聚合和輸出的目的,中間通過(guò) State 來(lái)維護(hù)中間狀態(tài)。
- 第二種類(lèi)型的作業(yè)是處理有限數(shù)據(jù)集的作業(yè)
數(shù)據(jù)可能是保存在文件中,或者是以其他方式提前保留下來(lái)的一個(gè)有限數(shù)據(jù)集。此時(shí)可以把有限數(shù)據(jù)集看作是無(wú)限數(shù)據(jù)集的一個(gè)特例,所以它可以自然的跑在之前的流處理模式之上,無(wú)需經(jīng)過(guò)代碼修改,可以直接支持。
但這里可能會(huì)忽略掉有限數(shù)據(jù)集數(shù)據(jù)有限的特點(diǎn),在接口上還需要處理更細(xì)粒度的時(shí)間、Watermark 等語(yǔ)義,可能會(huì)引入額外的復(fù)雜性。另外,在性能方面,因?yàn)槭前戳鞯姆绞教幚?#xff0c;在一開(kāi)始就需要把所有的任務(wù)拉起來(lái),可能需要占用更多的資源,如果采用的是 RocksDB backend,相當(dāng)于是一個(gè)大的 Hash 表,在 key 比較多的情況下,可能會(huì)有隨機(jī) IO 訪(fǎng)問(wèn)的問(wèn)題。
但是在批執(zhí)行模式下,可以通過(guò)排序的方式,用一種 IO 更加友好的方式來(lái)實(shí)現(xiàn)整個(gè)數(shù)據(jù)處理的流程。所以說(shuō),批處理模式在考慮數(shù)據(jù)有限的前提下,在調(diào)度、Shuffle、算子的實(shí)現(xiàn)上都給我們提供了更大的選擇空間。
最后,針對(duì)有限數(shù)據(jù)流,不管是采用哪種處理模式,我們希望最終的處理結(jié)果都是一致的。
1.4 近期演進(jìn)
Flink 在最近的幾個(gè)版本中,在 API 和實(shí)現(xiàn)層都朝著流批一體的目標(biāo)做了很多的努力。
- 在 Flink 1.11 及之前:
Flink 統(tǒng)一了 Table/SQL API,并引入了統(tǒng)一的 blink planner,blink planner 對(duì)流和批都會(huì)翻譯到 DataStream 算子之上。此外,對(duì)流和批還引入了統(tǒng)一的 shuffle 架構(gòu)。
- 在 Flink 1.12 中:
針對(duì)批的 shuffle 引入了一種新的基于 Sort-Merge 的 shuffle 模式,相對(duì)于之前 Flink 內(nèi)置的 Hash shuffle,性能會(huì)有很大提升。在調(diào)度方面,Flink 引入了一種基于 Pipeline Region 的流批一體的調(diào)度器。
- 在 Flink 1.13 中:
完善了 Sort-Merge Shuffle,并對(duì) Pipeline Region scheduler 在大規(guī)模作業(yè)下進(jìn)行了性能優(yōu)化。另外,前面提到過(guò),對(duì)于有限流的兩種執(zhí)行模式,我們預(yù)期它的執(zhí)行結(jié)果應(yīng)該是一致的。但是現(xiàn)在 Flink 在作業(yè)執(zhí)行結(jié)束的時(shí)候還有一些問(wèn)題,導(dǎo)致它并不能完全達(dá)到一致。
所以在 1.13 中,還有一部分的工作是針對(duì)有限數(shù)據(jù)集作業(yè),怎么在流批,尤其是在流的模式下,使它的結(jié)果和預(yù)期的結(jié)果保持一致。
- 未來(lái)的 Flink 1.14:
需要繼續(xù)完成有限作業(yè)一致性保證、批流切換 Source、逐步廢棄 DataSet API 等工作。
2. 運(yùn)行時(shí)優(yōu)化
2.1 大規(guī)模作業(yè)調(diào)度優(yōu)化
2.1.1 邊的時(shí)間復(fù)雜度問(wèn)題
Flink 提交作業(yè)時(shí)會(huì)生成一個(gè)作業(yè)的 DAG 圖,由多個(gè)頂點(diǎn)組成,頂點(diǎn)對(duì)應(yīng)著我們實(shí)際的處理節(jié)點(diǎn),如 Map。每個(gè)處理節(jié)點(diǎn)都會(huì)有并發(fā)度,此前 Flink 的實(shí)現(xiàn)里,當(dāng)我們把作業(yè)提交到 JM 之后,JM 會(huì)對(duì)作業(yè)展開(kāi),生成一個(gè) Execution Graph。
如下圖,作業(yè)有兩個(gè)節(jié)點(diǎn),并發(fā)度分別為 2 和 3。在 JM 中實(shí)際維護(hù)的數(shù)據(jù)結(jié)構(gòu)里,會(huì)分別維護(hù) 2 個(gè) task 和 3 個(gè) task,并由 6 條執(zhí)行邊組成,Flink 基于此數(shù)據(jù)結(jié)構(gòu)來(lái)維護(hù)整個(gè)作業(yè)的拓?fù)湫畔ⅰT谶@個(gè)拓?fù)湫畔⒌幕A(chǔ)上,Flink 可以單獨(dú)維護(hù)每個(gè) task 的狀態(tài),當(dāng)任務(wù)掛了之后以識(shí)別需要拉起的 task。
如果以這種 all-to-all 的通信,也就是每?jī)蓚€(gè)上下游 task 之間都有邊的情況下,上游并發(fā) 下游并發(fā),將出現(xiàn) O(N^2) 的數(shù)據(jù)結(jié)構(gòu)。這種情況下,內(nèi)存的占用是非常驚人的,如果是 10k 10k 的邊,JM 的內(nèi)存占用將達(dá)到 4.18G。此外,作業(yè)很多的計(jì)算復(fù)雜度都是和邊的數(shù)量相關(guān)的,此時(shí)的空間復(fù)雜度為 O(N^2) 或 O(N^3),如果是 10k * 10k 的邊,作業(yè)初次調(diào)度時(shí)間將達(dá)到 62s。
可以看出,除了初始調(diào)度之外,對(duì)于批作業(yè)來(lái)說(shuō),有可能是上游執(zhí)行完之后繼續(xù)執(zhí)行下游,中間的調(diào)度復(fù)雜度都是 O(N^2) 或 O(N^3),這樣就會(huì)導(dǎo)致很大的性能開(kāi)銷(xiāo)。另外,內(nèi)存占用很大的話(huà),GC 的性能也不會(huì)特別好。
2.1.2 Execution Graph 的對(duì)稱(chēng)性
針對(duì) Flink 在大規(guī)模作業(yè)下內(nèi)存和性能方面存在的一些問(wèn)題,經(jīng)過(guò)一些深入分析,可以看出上述例子中上下游節(jié)點(diǎn)之間是有一定對(duì)稱(chēng)性的。
?
Flink 中 “邊” 的類(lèi)型可以分為兩種:
- 一種是 Pointwise 型,上游和下游是一一對(duì)應(yīng)的,或者上游一個(gè)對(duì)應(yīng)下游幾個(gè),不是全部相連的,這種情況下,邊的數(shù)量基本是線(xiàn)性的 O(N), 和算子數(shù)在同一個(gè)量級(jí)。
- 另一種是 All-to-all 型,上游每一個(gè) task 都要和下游的每一個(gè) task 相連,在這種情況下可以看出,每一個(gè)上游的 task 產(chǎn)生的數(shù)據(jù)集都要被下游所有的 task 消費(fèi),實(shí)際上是一個(gè)對(duì)稱(chēng)的關(guān)系。只要記住上游的數(shù)據(jù)集會(huì)被下游的所有 task 來(lái)消費(fèi),就不用再單獨(dú)存中間的邊了。
所以,Flink 在 1.13 中對(duì)上游的數(shù)據(jù)集和下游的節(jié)點(diǎn)分別引入了 ResultPartitionGroup 和 VertexGroup 的概念。尤其是對(duì)于 All-to-all 的邊,因?yàn)樯舷掠沃g是對(duì)稱(chēng)的,可以把所有上游產(chǎn)生的數(shù)據(jù)集放到一個(gè) Group 里,把下游所有的節(jié)點(diǎn)也放到一個(gè) Group 里,在實(shí)際維護(hù)時(shí)不需要存中間的邊的關(guān)系,只需要知道上游的哪個(gè)數(shù)據(jù)集是被下游的哪個(gè) Group 消費(fèi),或下游的哪個(gè)頂點(diǎn)是消費(fèi)上游哪個(gè) Group 的數(shù)據(jù)集。
通過(guò)這種方式,減少了內(nèi)存的占用。
另外,在實(shí)際做一些調(diào)度相關(guān)計(jì)算的時(shí)候,比如在批處理里,假如所有的邊都是 blocking 邊的情況下,每個(gè)節(jié)點(diǎn)都屬于一個(gè)單獨(dú)的 region。之前計(jì)算 region 之間的上下游關(guān)系,對(duì)上游的每個(gè)頂點(diǎn),都需要遍歷其下游的所有頂點(diǎn),所以是一個(gè) O(N^2) 的操作。
而引入 ConsumerGroup 之后,就會(huì)變成一個(gè) O(N) 的線(xiàn)性操作。
2.1.3 優(yōu)化結(jié)果
經(jīng)過(guò)以上數(shù)據(jù)結(jié)構(gòu)的優(yōu)化,在 10k * 10k 邊的情況下,可以將 JM 內(nèi)存占用從 4.18G 縮小到 12.08M, 初次調(diào)度時(shí)間長(zhǎng)從 62s 縮減到 12s。這個(gè)優(yōu)化其實(shí)是非常顯著的,對(duì)用戶(hù)來(lái)說(shuō),只要升級(jí)到 Flink 1.13 就可以獲得收益,不需要做任何額外的配置。
2.2 Sort-Merge Shuffle
另外一個(gè)優(yōu)化,是針對(duì)批的作業(yè)在數(shù)據(jù) shuffle 方面做的優(yōu)化。一般情況下,批的作業(yè)是在上游跑完之后,會(huì)先把結(jié)果寫(xiě)到一個(gè)中間文件里,然后下游再?gòu)闹虚g文件里拉取數(shù)據(jù)進(jìn)行處理。
這種方式的好處就是可以節(jié)省資源,不需要上游和下游同時(shí)起來(lái),在失敗的情況下,也不需要從頭執(zhí)行。這是批處理的常用執(zhí)行方式。
?
2.2.1 Hash Shuffle
那么,shuffle 過(guò)程中,中間結(jié)果是如何保存到中間文件,下游再拉取的?
之前 Flink 引入的是 Hash shuffle,再以 All-to-all 的邊舉例,上游 task 產(chǎn)生的數(shù)據(jù)集,會(huì)給下游的每個(gè) task 寫(xiě)一個(gè)單獨(dú)的文件,這樣系統(tǒng)可能會(huì)產(chǎn)生大量的小文件。并且不管是使用文件 IO 還是 mmap 的方式,寫(xiě)每個(gè)文件都至少使用一塊緩沖區(qū),會(huì)造成內(nèi)存浪費(fèi)。下游 task 隨機(jī)讀取的上游數(shù)據(jù)文件,也會(huì)產(chǎn)生大量隨機(jī) IO。
所以,之前 Flink 的 Hash shuffle 應(yīng)用在批處理中,只能在規(guī)模比較小或者在用 SSD 的時(shí)候,在生產(chǎn)上才能比較 work。在規(guī)模比較大或者 SATA 盤(pán)上是有較大的問(wèn)題的。
2.2.2 Sort Shuffle
所以,在 Flink 1.12 和 Flink 1.13 中,經(jīng)過(guò)兩個(gè)版本,引入了一種新的基于 Sort Merge 的 shuffle。這個(gè) Sort 并不是指對(duì)數(shù)據(jù)進(jìn)行 Sort,而是對(duì)下游所寫(xiě)的 task 目標(biāo)進(jìn)行 Sort。
大致的原理是,上游在輸出數(shù)據(jù)時(shí),會(huì)使用一個(gè)固定大小的緩沖區(qū),避免緩沖區(qū)的大小隨著規(guī)模的增大而增大,所有的數(shù)據(jù)都寫(xiě)到緩沖區(qū)里,當(dāng)緩沖區(qū)滿(mǎn)時(shí),會(huì)做一次排序并寫(xiě)到一個(gè)單獨(dú)文件里,后面的數(shù)據(jù)還是基于此緩存區(qū)繼續(xù)寫(xiě),續(xù)寫(xiě)的一段會(huì)拼到原來(lái)的文件后面。最后單個(gè)的上游任務(wù)會(huì)產(chǎn)生一個(gè)中間文件,由很多段組成,每個(gè)段都是有序的結(jié)構(gòu)。
和其他的批處理的框架不太一樣,這邊并不是基于普通的外排序。一般的外排序是指會(huì)把這些段再做一次單獨(dú)的 merge,形成一個(gè)整體有序的文件,這樣下游來(lái)讀的時(shí)候會(huì)有更好的 IO 連續(xù)性,防止每一段每一個(gè) task 要讀取的數(shù)據(jù)段都很小。但是,這種 merge 本身也是要消耗大量的 IO 資源的,有可能 merge 的時(shí)間帶來(lái)的開(kāi)銷(xiāo)會(huì)遠(yuǎn)超過(guò)下游順序讀帶來(lái)的收益。
所以,這里采用了另外一種方式:在下游來(lái)請(qǐng)求數(shù)據(jù)的時(shí)候,比如下圖中的 3 個(gè)下游都要來(lái)讀上游的中間文件,會(huì)有一個(gè)調(diào)度器對(duì)下游請(qǐng)求要讀取的文件位置做一個(gè)排序,通過(guò)在上層增加 IO 調(diào)度的方式,來(lái)實(shí)現(xiàn)整個(gè)文件 IO 讀取的連續(xù)性,防止在 SATA 盤(pán)上產(chǎn)生大量的隨機(jī) IO。
在 SATA 盤(pán)上,相對(duì)于 Hash shuffle,Sort shuffle 的 IO 性能可以提高 2~8 倍。通過(guò) Sort shuffle,使得 Flink 批處理基本達(dá)到了生產(chǎn)可用的狀態(tài),在 SATA 盤(pán)上 IO 性能可以把磁盤(pán)打到 100 多M,而 SATA 盤(pán)最高也就能達(dá)到 200M 的讀寫(xiě)速度。
為了保持兼容性,Sort shuffle 并不是默認(rèn)啟用的,用戶(hù)可以控制下游并發(fā)達(dá)到多少來(lái)啟用 Sort Merge Shuffle。并且可以通過(guò)啟用壓縮來(lái)進(jìn)一步提高批處理的性能。Sort Merge shuffle 并沒(méi)有額外占用內(nèi)存,現(xiàn)在占用的上游讀寫(xiě)的緩存區(qū),是從 framework.off-heap 中抽出的一塊。
3. DataStream API 優(yōu)化
3.1 2PC & 端到端一致性
為了保證端到端的一致性,對(duì)于 Flink 流作業(yè)來(lái)說(shuō),是通過(guò)兩階段提交的機(jī)制來(lái)實(shí)現(xiàn)的,結(jié)合了 Flink 的 checkpoint、failover 機(jī)制和外部系統(tǒng)的一些特性。
大概的邏輯是,當(dāng)我想做端到端的一致性,比如讀取 Kafka 再寫(xiě)到 Kafka,在正常處理時(shí)會(huì)把數(shù)據(jù)先寫(xiě)到一個(gè) Kafka 的事務(wù)里,當(dāng)做 checkpoint 時(shí)進(jìn)行 preCommit,這樣數(shù)據(jù)就不會(huì)再丟了。
如果 checkpoint 成功的話(huà),會(huì)進(jìn)行一次正式的 commit。這樣就保證了外部系統(tǒng)的事務(wù)和 Flink 內(nèi)部的 failover 是一致的,比如 Flink 發(fā)生了 failover 需要回滾到上一個(gè) checkpoint , 外部系統(tǒng)中跟這一部分對(duì)應(yīng)的事務(wù)也會(huì)被 abort 掉,如果 checkpoint 成功了,外部事務(wù)的 commit 也會(huì)成功。
Flink 端到端的一致性依賴(lài)于 checkpoint 機(jī)制。但是,在遇到有限流時(shí),就會(huì)有一些問(wèn)題:
- 具有有限流的作業(yè),task 結(jié)束之后,Flink 是不支持做 checkpoint 的,比如流批混合的作業(yè),其中有一部分會(huì)結(jié)束,之后 Flink 就沒(méi)辦法再做 checkpoint,數(shù)據(jù)也就不會(huì)再提交了。
- 在有限流數(shù)據(jù)結(jié)束時(shí),因?yàn)?checkpoint 是定時(shí)執(zhí)行的,不能保證最后一個(gè) checkpoint 一定能在處理完所有數(shù)據(jù)后執(zhí)行,可能導(dǎo)致最后一部分?jǐn)?shù)據(jù)無(wú)法提交。
以上就會(huì)導(dǎo)致在流模式下,有限流作業(yè)流/批執(zhí)行模式結(jié)果不一致。
3.2 支持部分 Task 結(jié)束后的 Checkpoint (進(jìn)行中)
從 Flink 1.13 開(kāi)始,支持在一部分 task 結(jié)束之后,也能做 checkpoint。checkpoint 實(shí)際上是維護(hù)了每個(gè)算子的所有 task 的狀態(tài)列表。
在有一部分 task 結(jié)束之后,如下圖的虛線(xiàn)部分。Flink 會(huì)把結(jié)束的 task 分為兩種:
- 如果一個(gè)算子的所有 subtask 都已經(jīng)結(jié)束了,就會(huì)為這個(gè)算子存一個(gè) finished 標(biāo)記。
- 如果一個(gè)算子只有部分 task 結(jié)束,就只存儲(chǔ)未結(jié)束的 task 狀態(tài)。
基于這個(gè) checkpoint ,當(dāng) failover 之后還是會(huì)拉起所有算子,如果識(shí)別到算子的上一次執(zhí)行已經(jīng)結(jié)束,即 finsihed = true,就會(huì)跳過(guò)這個(gè)算子的執(zhí)行。尤其是針對(duì) Source 算子來(lái)說(shuō),如果已經(jīng)結(jié)束,后面就不會(huì)再重新執(zhí)行發(fā)送數(shù)據(jù)了。通過(guò)上述方式就可以保證整個(gè)狀態(tài)的一致性,即使有一部分 task 結(jié)束,還是照樣走 checkpoint。
Flink 也重新整理了結(jié)束語(yǔ)義。現(xiàn)在 Flink 作業(yè)結(jié)束有幾種可能:
- 作業(yè)結(jié)束:數(shù)據(jù)是有限的,有限流作業(yè)正常結(jié)束;
- stop-with-savepoint ,采一個(gè) savepoint 結(jié)束;
- stop-with-savepoint --drain ,采一個(gè) savepoint 結(jié)束,并會(huì)將 watermark 推進(jìn)到正無(wú)窮大。
之前這邊是兩種不同的實(shí)現(xiàn)邏輯,并且都有最后一部分?jǐn)?shù)據(jù)無(wú)法提交的問(wèn)題。
- 對(duì)作業(yè)結(jié)束和 stop-with-savepoint --drain 兩種語(yǔ)義,預(yù)期作業(yè)是不會(huì)再重啟的,都會(huì)對(duì)算子調(diào) endOfInput() , 通知算子通過(guò)一套統(tǒng)一的方式做 checkpoint 。
- 對(duì) stop-with-savepoint 語(yǔ)義,預(yù)期作業(yè)是會(huì)繼續(xù) savepoint 重啟的,此時(shí)就不會(huì)對(duì)算子調(diào) endOfInput()。后續(xù)會(huì)再做一個(gè) checkpoint , 這樣對(duì)于一定會(huì)結(jié)束并不再重啟的作業(yè),可以保證最后一部分?jǐn)?shù)據(jù)一定可以被提交到外部系統(tǒng)中。
4. 總結(jié)
在 Flink 的整個(gè)目標(biāo)里,其中有一點(diǎn)是期望做一個(gè)對(duì)有限數(shù)據(jù)集和無(wú)限數(shù)據(jù)集高效處理的統(tǒng)一平臺(tái)。目前基本上已經(jīng)有了一個(gè)初步的雛形,不管是在 API 方面,還是在 runtime 方面。下面來(lái)舉個(gè)例子說(shuō)明流批一體的好處。
針對(duì)用戶(hù)的回流作業(yè),平時(shí)是處理無(wú)限流的作業(yè),如果某一天想改個(gè)邏輯,用 stop-with-savepoint 方式把流停掉,但是這個(gè)變更邏輯還需要追回到前兩個(gè)月之內(nèi)的數(shù)據(jù)來(lái)保證結(jié)果的一致性。此時(shí),就可以啟一個(gè)批的作業(yè):作業(yè)不加修改,跑到提前緩存下來(lái)的輸入數(shù)據(jù)上,用批的模式可以盡快地訂正前兩個(gè)月的數(shù)據(jù)。另外,基于新的邏輯,使用前面保存的 savepoint,可以重啟一個(gè)新的流作業(yè)。
可以看出,在上述整個(gè)流程中,如果是之前流批分開(kāi)的情況,是需要單獨(dú)開(kāi)發(fā)作業(yè)進(jìn)行數(shù)據(jù)訂正的。但在流批一體的情況下,可以基于流的作業(yè)自然的進(jìn)行數(shù)據(jù)訂正,不需要用戶(hù)再做額外的開(kāi)發(fā)。
在 Flink 后續(xù)的版本中,還會(huì)進(jìn)一步考慮更多流批結(jié)合的場(chǎng)景,比如用戶(hù)先做一個(gè)批的處理,對(duì)狀態(tài)進(jìn)行初始化之后,再切到無(wú)限流上的場(chǎng)景。當(dāng)然,在流和批單獨(dú)的功能上,也會(huì)做進(jìn)一步的優(yōu)化和完善,使得 Flink 在流批方面都是具有競(jìng)爭(zhēng)力的計(jì)算框架。
原文鏈接:https://developer.aliyun.com/article/784968?
版權(quán)聲明:本文內(nèi)容由阿里云實(shí)名注冊(cè)用戶(hù)自發(fā)貢獻(xiàn),版權(quán)歸原作者所有,阿里云開(kāi)發(fā)者社區(qū)不擁有其著作權(quán),亦不承擔(dān)相應(yīng)法律責(zé)任。具體規(guī)則請(qǐng)查看《阿里云開(kāi)發(fā)者社區(qū)用戶(hù)服務(wù)協(xié)議》和《阿里云開(kāi)發(fā)者社區(qū)知識(shí)產(chǎn)權(quán)保護(hù)指引》。如果您發(fā)現(xiàn)本社區(qū)中有涉嫌抄襲的內(nèi)容,填寫(xiě)侵權(quán)投訴表單進(jìn)行舉報(bào),一經(jīng)查實(shí),本社區(qū)將立刻刪除涉嫌侵權(quán)內(nèi)容。總結(jié)
以上是生活随笔為你收集整理的Flink 1.13,面向流批一体的运行时与 DataStream API 优化的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 【直播回看】「EDGE X Kubern
- 下一篇: 重磅发布!阿里云云效《阿里巴巴DevOp