快手基于 Apache Flink 的优化实践
本次由快手劉建剛老師分享,內(nèi)容主要分為三部分。首先介紹流式計算的基本概念, 然后介紹 Flink 的關(guān)鍵技術(shù),最后講講 Flink 在快手生產(chǎn)實踐中的一些應(yīng)用,包括實時指標(biāo)計算和快速 failover。
?
一、流式計算的介紹
?
流式計算主要針對 unbounded data(無界數(shù)據(jù)流)進行實時的計算,將計算結(jié)果快速的輸出或者修正。
?
這部分將分為三個小節(jié)來介紹。第一,介紹大數(shù)據(jù)系統(tǒng)發(fā)展史,包括初始的批處理到現(xiàn)在比較成熟的流計算;第二,為大家簡單對比下批處理和流處理的區(qū)別;第三,介紹流式計算里面的關(guān)鍵問題,這是每個優(yōu)秀的流式計算引擎所必須面臨的問題。
?
1、大數(shù)據(jù)系統(tǒng)發(fā)展史
?
?
上圖是 2003 年到 2018 年大數(shù)據(jù)系統(tǒng)的發(fā)展史,看看是怎么一步步走到流式計算的。
?
2003 年,Google 的 MapReduce 橫空出世,通過經(jīng)典的 Map&Reduce 定義和系統(tǒng)容錯等保障來方便處理各種大數(shù)據(jù)。很快就到了 Hadoop,被認(rèn)為是開源版的 ?MapReduce, 帶動了整個apache開源社區(qū)的繁榮。再往后是谷歌的 Flume,通過算子連接等 pipeline 的方式解決了多個 MapReduce 作業(yè)連接處理低效的問題。
?
流式系統(tǒng)的開始以 Storm 來介紹。Storm 在2011年出現(xiàn), 具備延時短、性能高等特性, 在當(dāng)時頗受喜愛。但是 Storm 沒有提供系統(tǒng)級別的 failover 機制,無法保障數(shù)據(jù)一致性。那時的流式計算引擎是不精確的,lamda 架構(gòu)組裝了流處理的實時性和批處理的準(zhǔn)確性,曾經(jīng)風(fēng)靡一時,后來因為難以維護也逐漸沒落。
?
接下來出現(xiàn)的是 Spark Streaming,可以說是第一個生產(chǎn)級別的流式計算引擎。Spark Streaming 早期的實現(xiàn)基于成熟的批處理,通過 mini batch 來實現(xiàn)流計算,在 failover 時能夠保障數(shù)據(jù)的一致性。
?
Google 在流式計算方面有很多探索,包括 MillWheel、Cloud Dataflow、Beam,提出了很多流式計算的理念,對其他的流式計算引擎影響很大。
?
再來看 Kafka。Kafka 并非流式計算引擎,但是對流式計算影響特別大。Kafka 基于log 機制、通過 partition 來保存實時數(shù)據(jù),同時也能存儲很長時間的歷史數(shù)據(jù)。流式計算引擎可以無縫地與kafka進行對接,一旦出現(xiàn) Failover,可以利用 Kafka 進行數(shù)據(jù)回溯,保證數(shù)據(jù)不丟失。另外,Kafka 對 table 和 stream 的探索特別多,對流式計算影響巨大。
?
Flink 的出現(xiàn)也比較久,一直到 2016 年左右才火起來的。Flink 借鑒了很多 Google 的流式計算概念,使得它在市場上特別具有競爭力。后面我會詳細(xì)介紹 Flink 的一些特點。
?
2、批處理與流計算的區(qū)別
?
批處理和流計算有什么樣的區(qū)別,這是很多同學(xué)有疑問的地方。我們知道 MapReduce 是一個批處理引擎,Flink 是一個流處理引擎。我們從四個方面來進行一下對比:
?
1)使用場景
?
MapReduce 是大批量文件處理,這些文件都是 bounded data,也就是說你知道這個文件什么時候會結(jié)束。相比而言,Flink 處理的是實時的 unbounded data,數(shù)據(jù)源源不斷,可能永遠(yuǎn)都不會結(jié)束,這就給數(shù)據(jù)完備性和 failover 帶來了很大的挑戰(zhàn)。
?
2)容錯
?
MapReduce 的容錯手段包括數(shù)據(jù)落盤、重復(fù)讀取、最終結(jié)果可見等。文件落盤可以有效保存中間結(jié)果,一旦 task 掛掉重啟就可以直接讀取磁盤數(shù)據(jù),只有作業(yè)成功運行完了,最終結(jié)果才對用戶可見。這種設(shè)計的哲理就是你可以通過重復(fù)讀取同一份數(shù)據(jù)來產(chǎn)生同樣的結(jié)果,可以很好的處理 failover。
?
Flink 的容錯主要通過定期快照和數(shù)據(jù)回溯。每隔一段時間,Flink就會插入一些 barrier,barrier 從 source 流動到 sink,通過 barrier 流動來控制快照的生成。快照制作完就可以保存在共享引擎里。一旦作業(yè)出現(xiàn)問題,就可以從上次快照進行恢復(fù),通過數(shù)據(jù)回溯來重新消費。
?
3)性能
?
MapReduce 主要特點是高吞吐、高延時。高吞吐說明處理的數(shù)據(jù)量非常大;高延時就是前面說到的容錯問題,它必須把整個作業(yè)處理完才對用戶可見。
?
Flink 主要特點是高吞吐、低延時。在流式系統(tǒng)里,Flink 的吞吐是很高的。同時,它也可以做到實時處理和輸出,讓用戶快速看到結(jié)果。
?
4)計算過程
?
MapReduce 主要通過 Map 和 reduce 來計算。Map 負(fù)責(zé)讀取數(shù)據(jù)并作基本的處理, reduce 負(fù)責(zé)數(shù)據(jù)的聚合。用戶可以根據(jù)這兩種基本算子,組合出各種各樣的計算邏輯。
?
Flink 為用戶提供了 pipeline 的 API 和批流統(tǒng)一的 SQL。通過 pipeline ?的 API, 用戶可以方便地組合各種算子構(gòu)建復(fù)雜的應(yīng)用;Flink SQL 是一個更高層的 API 抽象,極大地降低了用戶的使用門檻。
?
3、流式計算的關(guān)鍵問題
?
這部分主要通過四個問題給大家解答流式計算的關(guān)鍵問題,也是很多計算引擎需要考慮的問題。
?
1)What
?
What 是指通過什么樣的算子來進行計算。主要包含三個方面的類型,element-wise 表示一對一的計算,aggregating 表示聚合操作,composite 表示多對多的計算。
?
2)Where
?
aggregating 會進行一些聚合的計算, 主要是在各種 window 里進行計算。窗口包含滑動窗口、滾動窗口、會話窗口。窗口會把無界的數(shù)據(jù)切分成有界的一個個數(shù)據(jù)塊進行處理,后面我們會詳細(xì)介紹這點。
?
3)When
?
When 就是什么時候觸發(fā)計算。窗口里面有數(shù)據(jù),由于輸入數(shù)據(jù)是無窮無盡的,很難知道一個窗口的數(shù)據(jù)是否全部到達了。流式計算主要通過 watermark 來保障數(shù)據(jù)的完備性,通過 trigger 來決定何時觸發(fā)。當(dāng)接收到數(shù)值為 X 的 Watermark 時,可以認(rèn)為所有時間戳小于等于X的事件全部到達了。一旦 watermark 跨過窗口結(jié)束時間,就可以通過 trigger 來觸發(fā)計算并輸出結(jié)果。
?
4)How
?
How 主要指我們?nèi)绾沃匦露x同一窗口的多次觸發(fā)結(jié)果。前面也說了 trigger 是用來觸發(fā)窗口的, 一個窗口可能會被觸發(fā)多次,比如1分鐘的窗口每 10 秒觸發(fā)計算一次。處理方式主要包含三種:
?
- Discarding,丟棄之前的狀態(tài)重新計算。這種方式每次的觸發(fā)結(jié)果都是互不關(guān)聯(lián)的,多次觸發(fā)結(jié)果的組合反映了全部的窗口內(nèi)容,下游一般會再次聚合;
- Accumulating,這個就是一個聚合的狀態(tài),比如說第二次觸發(fā)的時候是在第一次的結(jié)果上進行計算的,下游只需要保存最新的結(jié)果即可;
- Accumulating 和 retracting,這個主要在 Accumulating 的基礎(chǔ)上加了一個 retracting,retracting 的意思就是撤銷。窗口再次觸發(fā)時,會告訴下游撤銷上一次的計算結(jié)果,并告知最新的結(jié)果。Flink SQL 的聚合就使用了這種 retract的模式。
?
二、Flink 關(guān)鍵技術(shù)
?
1、Flink 簡介
?
Flink 是一款分布式計算引擎, 既可以進行流式計算,也可以進行批處理。下圖是官網(wǎng)對 Flink 的介紹:
?
?
Flink 可以運行在 k8s、yarn、mesos 等資源調(diào)度平臺上,依賴 hdfs 等文件系統(tǒng),輸入包含事件和各種其他數(shù)據(jù),經(jīng)過 Flink 引擎計算后再輸出到其他中間件或者數(shù)據(jù)庫等。
?
Flink 有兩個核心概念:
?
- State:Flink 可以處理有狀態(tài)的數(shù)據(jù),通過自身的 state 機制來保障作業(yè)failover時數(shù)據(jù)不丟失;
- Event Time:允許用戶按照事件時間來處理數(shù)據(jù),通過 watermark 來推動時間前進,這個后面還會詳細(xì)介紹。主要是系統(tǒng)的時間和事件的時間。
?
Flink 主要通過上面兩個核心技術(shù)來保證 exactly-once, 比如說作業(yè) Failover 的時候狀態(tài)不丟失,就好像沒發(fā)生故障一樣。
?
2、快照機制
?
Flink 的快照機制主要是為了保障作業(yè) failover 時不丟失狀態(tài)。Flink 提供了一種輕量級的快照機制,不需要停止作業(yè)就可以幫助用戶持久化內(nèi)存中的狀態(tài)數(shù)據(jù)。
?
?
上圖中的 markers(與 barrier 語義相同)通過流動來觸發(fā)快照的制作,每一個編號都代表了一次快照,比如編號為 n 的 markers 從最上游流動到最下游就代表了一次快照的制作過程。簡述如下:
?
- 系統(tǒng)發(fā)送編號為 n 的 markers 到最上游的算子,markers 隨著數(shù)據(jù)往下游流動;
- 當(dāng)下游算子收到 marker 后,就開始將自身的狀態(tài)保存到共享存儲中;
- 當(dāng)所有最下游的算子接收到 marker 并完成算子快照后,本次作業(yè)的快照制作完成。
?
一旦作業(yè)失敗,重啟時就可以從快照恢復(fù)。
?
下面為一個簡單的 demo 說明(barrier 等同于 marker)。
?
?
- barrier 到達 Source,將狀態(tài) offset=7 存儲到共享存儲;
- barrier 到達 Task,將狀態(tài) sum=21 存儲到共享存儲;
- barrier 到達 Sink,commit 本次快照,標(biāo)志著快照的成功制作。
?
?
這時候突然間作業(yè)也掛掉, 重啟時 Flink 會通過快照恢復(fù)各個狀態(tài)。Source 會將自身的 offset 置為 7,Task 會將自身的 sum 置為 21。現(xiàn)在我們可以認(rèn)為 1、2、3、4、5、6 這 6 個數(shù)字的加和結(jié)果并沒有丟失。這個時候,offset 從 7 開始消費,跟作業(yè)失敗前完全對接了起來,確保了 exactly-once。
?
3、事件時間
?
時間類型分為兩種:
?
- Event time(事件時間),指事件發(fā)生的時間,比如采集數(shù)據(jù)時的時間;
- Processing time(系統(tǒng)時間),指系統(tǒng)的時間,比如處理數(shù)據(jù)時的時間。
?
如果你對數(shù)據(jù)的準(zhǔn)確性要求比較高的話,采用 Event time 能保障 exactly-once。Processing Time 一般用于實時消費、精準(zhǔn)性要求略低的場景,主要是因為時間生成不是 deterministic。
?
我們可以看下面的關(guān)系圖, X 軸是 Event time,Y 軸是 Processing time。理想情況下 Event time 和 Processing time 是相同的,就是說只要有一個事件發(fā)生,就可以立刻處理。但是實際場景中,事件發(fā)生后往往會經(jīng)過一定延時才會被處理,這樣就會導(dǎo)致我們系統(tǒng)的時間往往會滯后于事件時間。這里它們兩個的差 Processing-time lag 表示我們處理事件的延時。
?
?
事件時間常用在窗口中,使用 watermark 來確保數(shù)據(jù)完備性,比如說 watermarker 值大于 window 末尾時間時,我們就可以認(rèn)為 window 窗口所有數(shù)據(jù)都已經(jīng)到達了,就可以觸發(fā)計算了。
?
?
比如上面 [0-10] 的窗口,現(xiàn)在 watermark 走到了 10,已經(jīng)到達了窗口的結(jié)束,觸發(fā)計算 SUM=21。如果要是想對遲到的數(shù)據(jù)再進行觸發(fā),可以再定義一下后面 late data 的觸發(fā),比如說后面來了個 9,我們的 SUM 就等于 30。
?
4、窗口機制
?
窗口機制就是把無界的數(shù)據(jù)分成數(shù)據(jù)塊來進行計算,主要有三種窗口。
?
- 滾動窗口:固定大小的窗口,相鄰窗口沒有交集;
- 滑動窗口:每個窗口的大小是一樣的,但是兩個窗口之間會有重合;
- 會話窗口:根據(jù)活躍時間聚合而成的窗口, 比如活躍時間超過3分鐘新起一個窗口。窗口之間留有一定的間隔。
?
?
窗口會自動管理狀態(tài)和觸發(fā)計算,Flink 提供了豐富的窗口函數(shù)來進行計算。主要包括以下兩種:
?
- ProcessWindowFunction,全量計算會把所有數(shù)據(jù)緩存到狀態(tài)里,一直到窗口結(jié)束時統(tǒng)一計算。相對來說,狀態(tài)會比較大,計算效率也會低一些;
- AggregateFunction,增量計算就是來一條數(shù)據(jù)就算一條,可能我們的狀態(tài)就會特別的小,計算效率也會比 ProcessWindowFunction 高很多,但是如果狀態(tài)存儲在磁盤頻繁訪問狀態(tài)可能會影響性能。
?
?
三、快手 Flink 實踐
?
1、應(yīng)用概括
?
快手應(yīng)用概括主要是分為數(shù)據(jù)接入、Flink 實時計算、數(shù)據(jù)應(yīng)用、數(shù)據(jù)展示四個部分。各層各司其職、銜接流暢,為用戶提供一體化的數(shù)據(jù)服務(wù)流程。
?
?
2、實時指標(biāo)計算
?
常見的實時指標(biāo)計算包括 uv、pv 和 sum。這其中 uv 的計算最為復(fù)雜也最為經(jīng)典。下面我將重點介紹 uv。
?
uv 指的是不同用戶的個數(shù),我們這邊計算的就是不同 deviceld 的個數(shù),主要的挑戰(zhàn)來自三方面:
?
- 用戶數(shù)多,數(shù)據(jù)量大。活動期間的 QPS 經(jīng)常在千萬級別,實際計算起來特別復(fù)雜;
- 實時性要求高,通常為幾秒到分鐘結(jié)果的輸出;
- 穩(wěn)定性要求高,比如說我們在做春晚活動時候要求故障時間需要低于2%或更少。
?
針對各種各樣的 uv 計算,我們提供了一套成熟的計算流程。主要包含了三方面:
?
- 字典方案:將 string 類型的 deviceld 轉(zhuǎn)成 long 類型,方便后續(xù)的 uv 計算;
- 傾斜處理:比如某些大 V 會導(dǎo)致數(shù)據(jù)嚴(yán)重傾斜,這時候就需要打散處理;
- 增量計算:比如計算 1 天的 uv,每分鐘輸出一次結(jié)果。
?
字典方案需要確保任何兩個不同的 deviceId 不能映射到相同的 long 類型數(shù)字上。快手內(nèi)部主要使用過以下三種方案:
?
?
- HBase, 基于 partition 分區(qū)建立 deviceld 到 id 的映射, 通過緩存和批量訪問來加速;
- Redis, 這種方案嚴(yán)格來說不屬于字典,主要通過 key-value 來判斷數(shù)據(jù)是否首次出現(xiàn),基于首次數(shù)據(jù)來計算 uv,這樣就會把 pv 和 uv 的計算進行統(tǒng)一;
- 最后就是一個 Flink 內(nèi)部自建的全局字典實現(xiàn) deviceld 到 id 的轉(zhuǎn)換,之后計算UV。
?
這三種方案里面,前兩種屬于外部存儲的字典方案,優(yōu)點是可以做到多個作業(yè)共享 1 份數(shù)據(jù), 缺點是外部訪問慢而且不太穩(wěn)定。最后一種 Flink 字典方案基于 state,不依賴外部存儲, 性能高但是無法多作業(yè)共享。
?
接下來我們重點介紹基于Flink自身的字典方案,下圖主要是建立一個 deviceld 到 id 的映射:
?
?
主要分成三步走:
?
1)建立 Partition 分區(qū), 指定一個比較大的 Partition 分區(qū)個數(shù),該個數(shù)比較大并且不會變,根據(jù) deviceld 的哈希值將其映射到指定 partition。
?
2)建立 id 映射。每個 Partition 都有自己負(fù)責(zé)的 id 區(qū)間,確保 Partition 之間的long 類型的 id 不重復(fù), partition 內(nèi)部通過自增 id 來確保每個 deviceId 對應(yīng)一個 id。
?
3)使用 keyed state 保存 id 映射。這樣我們的作業(yè)出現(xiàn)并發(fā)的大改變時,可以方便的 rescale,不需要做其他的操作。
?
除了 id 轉(zhuǎn)換,后面就是一個實時指標(biāo)計算的常見問題,就是數(shù)據(jù)傾斜。業(yè)界常見的解決數(shù)據(jù)傾斜處理方案主要是兩種:
?
- 打散再聚合:先將傾斜的數(shù)據(jù)打散計算,然后再聚合計算結(jié)果;
- Local-aggregate:先在本地計算預(yù)聚合,這樣會大大減少下游的數(shù)據(jù)壓力。
?
二者的本質(zhì)是一樣的,都是先預(yù)聚合再匯總,從而避免單點性能問題。
?
?
上圖為計算最小值的熱點問題,紅色數(shù)據(jù)為熱點數(shù)據(jù)。如果直接將它們打到同一個分區(qū),會出現(xiàn)性能問題。為了解決傾斜問題,我們通過hash策略將數(shù)據(jù)分成小的 partition 來計算,如上圖的預(yù)計算,最后再將中間結(jié)果匯總計算。
?
當(dāng)一切就緒后,我們來做增量的 UV 計算,比如計算 1 天 uv,每分鐘輸出 1 次結(jié)果。計算方式既可以采用 API,也可以采用 SQL。
?
針對 API,我們選擇了 global state+bitmap 的組合,既嚴(yán)格遵循了 Event Time 又減少了 state 大小:
?
?
下面為計算流程(需要注意時區(qū)問題):
?
- 定義跟觸發(fā)間隔一樣大小的 window(比如 1 分鐘);
- Global state 用來保存跨窗口的狀態(tài),我們采用 bitmap 來存儲狀態(tài);
- 每隔一個 window 觸發(fā)一次,輸出起始至今的 UV;
- 當(dāng)前作用域(比如 1 天)結(jié)束,清空狀態(tài)重新開始。
?
針對 SQL,增量計算支持的還不是那么完善,但是可以利用 early-fire 的參數(shù)來提前觸發(fā)窗口。
?
配置如下:
?
table.exec.emit.early-fire.enabled: truetable.exec.emit.early-fire.delay:60 s?
early-fire.delay 就是每分鐘輸出一次結(jié)果的意思。
SQL 如下:
?
SELECT TUMBLE_ROWTIME(eventTime, interval ‘1’ day) AS rowtime, dimension, count(distinct id) as uv FROM person GROUP BY TUMBLE(eventTime, interval '1' day), dimension?
如果遇到傾斜,可以參考上一步來處理。
?
3、快速 failover
?
最后看下我們部門最近發(fā)力的一個方向,如何快速 failover。
?
Flink 作業(yè)都是 long-running 的在線作業(yè),很多對可用性的要求特別高,尤其是跟公司核心業(yè)務(wù)相關(guān)的作業(yè),SLA 要求 4 個 9 甚至更高。當(dāng)作業(yè)遇到故障時,如何快速恢復(fù)對我們來說是一個巨大的挑戰(zhàn)。
?
下面分三個方面來展開:
?
- Flink 當(dāng)前已有的快速恢復(fù)方案;
- 基于 container 宕掉的快速恢復(fù);
- 基于機器宕掉的快速恢復(fù)。
?
1)Flink 當(dāng)前已有的快速恢復(fù)方案
?
Flink 當(dāng)前已有的快速恢復(fù)方案主要包括以下兩種:
?
- region failover。如果流式作業(yè)的 DAG 包含多個子圖或者 pipeline,那么 task 失敗時只會影響其所屬的子圖或者 pipeline ,而不用整個 DAG 都重新啟動;
- local recovery。在 Flink 將快照同步到共享存儲的同時,在本地磁盤也保存一份快照。作業(yè)失敗恢復(fù)時,可以調(diào)度到上次部署的位置,并從 local disk 進行快照恢復(fù)。
?
2)基于 container 宕掉的快速恢復(fù)
?
實際環(huán)境中, container 宕掉再申請有時會長達幾十秒,比如因為 hdfs 慢、yarn 慢等原因,嚴(yán)重影響恢復(fù)速度。為此,我們做了如下優(yōu)化:
?
- 冗余資源。維持固定個數(shù)的冗余 container,一旦 container 宕掉,冗余 container 立刻候補上來,省去了繁雜的資源申請流程;
- 提前申請。一旦發(fā)現(xiàn)作業(yè)因為 container 宕掉而失敗,立刻申請新的 container 。
?
?
以上優(yōu)化覆蓋了很大一部分場景,恢復(fù)時間從 30s-60s 降到 20s 以內(nèi)。
?
3)基于機器宕掉的快速恢復(fù)
?
機器宕掉時,flink on yarn 的恢復(fù)時間超過 3 分鐘,這對重要作業(yè)顯然是無法容忍的!為了做到快速恢復(fù),我們需要做到快速感知和恢復(fù):
?
- 冗余資源并打散分配,確保兩個冗余資源不在一個 container,redundantContainerNum=max(containerNumOfHost) + 1;
- 作業(yè)宕機,Hawk 監(jiān)測系統(tǒng) 5 秒內(nèi)發(fā)現(xiàn);
- 冗余資源快速候補,免去申請資源的流程。
?
?
通過這種方案,我們可以容忍任意一臺機器的宕機,并將宕機恢復(fù)時間由原先的 3 分鐘降低到 30 秒以內(nèi)。
?
四、總結(jié)
?
本文從大數(shù)據(jù)系統(tǒng)的發(fā)展入手,進而延伸出流式系統(tǒng)的關(guān)鍵概念,之后介紹了 Flink的關(guān)鍵特性,最后講解了快手內(nèi)部的實時指標(biāo)計算和快速 failover,希望對大家有所幫助。
?
五、Q&A
?
Q1:打算做實時計算,可以跳過 Storm、Spark 直接上手 Flink 嗎?
?
A:可以直接使用 Flink。Storm 在 failover 時會丟失數(shù)據(jù),無法做到 exactly-once;spark streaming 是 Flink 的競爭者,是在批處理的基礎(chǔ)上實現(xiàn)流計算,相比而言,Flink 的底層是流處理,更加適合流計算。
?
Q2:一般怎么處理 taskmanager heartbeat timeout?
?
A:默認(rèn) 10 秒?yún)R報一次心跳,心跳超時為 50 秒,這個時候作業(yè)會失敗,如果配置了高可用那么會重啟。
?
Q3:如何保證 2 天大時間跨度延遲消息的窗口計算?
?
A:這里主要的挑戰(zhàn)在于時間長、狀態(tài)大,建議 stateBakend 使用 Rocksdb(可以利用磁盤存儲大狀態(tài)),窗口計算建議使用增量計算來減少狀態(tài)的大小。
?
Q4:Flink on Yarn,Yarn 重啟會自動拉起 Flink 任務(wù)嗎,說不能拉起怎么處理,手動啟動嗎?
?
A:如果配置了高可用(依賴 zookeeper),作業(yè)失敗了就可以自動拉起。
?
Q5:Kafka 目前多用作數(shù)據(jù)中轉(zhuǎn)平臺,Flink 相當(dāng)于替代了 Kafka Stream 嗎?
?
?A:Kafka的核心功能是消息中間件,kafka stream 可以跟 kafka 很好的集成,但并不是一個專業(yè)的計算引擎。相比而言,flink 是一個分布式的流式計算引擎,功能上更加強大。
?
Q6:你們怎么看待 Apache Beam?
?
A:Apache Beam 在上層進行了抽象,可以類比 SQL,只定義規(guī)范,底層可以接入各種計算引擎。 ? ?
?
原文鏈接
本文為阿里云原創(chuàng)內(nèi)容,未經(jīng)允許不得轉(zhuǎn)載。
總結(jié)
以上是生活随笔為你收集整理的快手基于 Apache Flink 的优化实践的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【产品动态】一文详细解读智能数据构建产品
- 下一篇: 【详谈 Delta Lake 】系列技术