王海濤,曾經(jīng)在微軟的 SQL Server和大數(shù)據(jù)平臺(tái)組工作多年。帶領(lǐng)團(tuán)隊(duì)建立了微軟對(duì)內(nèi)的 Spark 服務(wù),主打 Spark Streaming。去年加入阿里實(shí)時(shí)計(jì)算部門,參與改進(jìn)阿里基于 Apache Flink 的Blink 平臺(tái)。
創(chuàng)新互聯(lián)"三網(wǎng)合一"的企業(yè)建站思路。企業(yè)可建設(shè)擁有電腦版、微信版、手機(jī)版的企業(yè)網(wǎng)站。實(shí)現(xiàn)跨屏營銷,產(chǎn)品發(fā)布一步更新,電腦網(wǎng)絡(luò)+移動(dòng)網(wǎng)絡(luò)一網(wǎng)打盡,滿足企業(yè)的營銷需求!創(chuàng)新互聯(lián)具備承接各種類型的成都網(wǎng)站設(shè)計(jì)、成都做網(wǎng)站、外貿(mào)網(wǎng)站建設(shè)項(xiàng)目的能力。經(jīng)過10余年的努力的開拓,為不同行業(yè)的企事業(yè)單位提供了優(yōu)質(zhì)的服務(wù),并獲得了客戶的一致好評(píng)。
導(dǎo)讀: 做大數(shù)據(jù)絕對(duì)躲不過的一個(gè)熱門話題就是實(shí)時(shí)流計(jì)算,而提到實(shí)時(shí)流計(jì)算,就不得不提 Spark 和 Flink。Spark 從 2014 年左右開始迅速流行,剛推出時(shí)除了在某些場景比 Hadoop MapReduce 帶來幾十到上百倍的性能提升外,還提出了用一個(gè)統(tǒng)一的引擎支持批處理、流處理、交互式查詢、機(jī)器學(xué)習(xí)等常見的數(shù)據(jù)處理場景。憑借高性能和全面的場景支持,Spark 早已成為眾多大數(shù)據(jù)開發(fā)者的最愛。
正在 Spark 如日中天高速發(fā)展的時(shí)候,2016 年左右 Flink 開始進(jìn)入大眾的視野并逐漸廣為人知。在人們開始使用 Spark 之后,發(fā)現(xiàn) Spark 雖然支持各種常見場景,但并不是每一種都同樣好用。數(shù)據(jù)流的實(shí)時(shí)處理就是其中相對(duì)較弱的一環(huán)。Flink 憑借更優(yōu)的流處理引擎,同時(shí)也支持各種處理場景,成為 Spark 的有力挑戰(zhàn)者。當(dāng)然,Spark 也在不斷增強(qiáng)其實(shí)時(shí)流處理能力,在今年 2 月份發(fā)布的 2.3 版本中引入了持續(xù)流式處理模型,可將流處理延遲降低至毫秒級(jí)別。
本文對(duì) Spark 和 Flink 的技術(shù)與場景進(jìn)行了全面分析與對(duì)比,且看下一代大數(shù)據(jù)計(jì)算引擎之爭,誰主沉???
自從數(shù)據(jù)處理需求超過了傳統(tǒng)數(shù)據(jù)庫能有效處理的數(shù)據(jù)量之后,Hadoop 等各種基于 MapReduce 的海量數(shù)據(jù)處理系統(tǒng)應(yīng)運(yùn)而生。從2004 年 Google 發(fā)表 MapReduce 論文開始,經(jīng)過近10年的發(fā)展,基于 Hadoop 開源生態(tài)或者其它相應(yīng)系統(tǒng)的海量數(shù)據(jù)處理已經(jīng)成為業(yè)界的基本需求。
但是,很多機(jī)構(gòu)在開發(fā)自己的數(shù)據(jù)處理系統(tǒng)時(shí)都會(huì)發(fā)現(xiàn)需要面臨一系列的問題。從數(shù)據(jù)中獲取價(jià)值需要的投入遠(yuǎn)遠(yuǎn)超過預(yù)期。常見的問題包括:
cdn.xitu.io/2019/4/28/16a630d7d05c167b?w=975&h=514&f=png&s=244600">
(來源:https://mapr.com/developercentral/lambda-architecture/)
上圖是一個(gè)典型的lambda架構(gòu),只是包含了批處理和流處理兩種場景,就已經(jīng)牽涉到至少四五種技術(shù)了,還不算每種技術(shù)的可替代選擇。再加上實(shí)時(shí)查詢,交互式分析,機(jī)器學(xué)習(xí)等場景,每個(gè)場景都有幾種技術(shù)可以選擇,每個(gè)技術(shù)涵蓋的領(lǐng)域還有不同方式的重疊。結(jié)果就是一個(gè)業(yè)務(wù)經(jīng)常需要使用四五種以上的技術(shù)才能支持好一個(gè)完整的數(shù)據(jù)處理流程。加上調(diào)研選型,需要了解的數(shù)目還要多得多。
下圖是大數(shù)據(jù)領(lǐng)域的全景。有沒有暈?
大數(shù)據(jù)和 AI 全景 – 2018 (來源:http://mattturck.com/bigdata2018/)
開發(fā)和運(yùn)行效率低下。因?yàn)闋可娴蕉喾N系統(tǒng),每種系統(tǒng)有自己的開發(fā)語言和工具,開發(fā)效率可想而知。而因?yàn)椴捎昧硕嗵紫到y(tǒng),數(shù)據(jù)需要在各個(gè)系統(tǒng)之間傳輸,也造成了額外的開發(fā)和運(yùn)行代價(jià),數(shù)據(jù)的一致也難以保證。在很多機(jī)構(gòu),實(shí)際上一半以上的開發(fā)精力花在了數(shù)據(jù)在各個(gè)系統(tǒng)之間的傳輸上。
復(fù)雜的運(yùn)維。多個(gè)系統(tǒng),每個(gè)需要自己的運(yùn)維,帶來更高的運(yùn)維代價(jià)的同時(shí)也提高了系統(tǒng)出問題的可能。
數(shù)據(jù)質(zhì)量難以保證。數(shù)據(jù)出了問題難以跟蹤解決。
了解了這些問題以后,對(duì)Spark 從2014年左右開始迅速流行就比較容易理解了。Spark 在當(dāng)時(shí)除了在某些場景比 Hadoop MapReduce 帶來幾十到上百倍的性能提升外,還提出了用一個(gè)統(tǒng)一的引擎支持批處理,流處理,交互式查詢,機(jī)器學(xué)習(xí)等常見的數(shù)據(jù)處理場景??催^在一個(gè) Notebook 里完成上述所有場景的 Spark 演示,對(duì)比之前的數(shù)據(jù)流程開發(fā),對(duì)很多開發(fā)者來說不難做出選擇。經(jīng)過幾年的發(fā)展,Spark 已經(jīng)被視為可以完全取代 Hadoop 中的 MapReduce 引擎。
正在 Spark 如日中天高速發(fā)展的時(shí)候,2016年左右 Flink 開始進(jìn)入大眾的視野并逐漸廣為人知。為什么呢?原來在人們開始使用 Spark 之后,發(fā)現(xiàn) Spark 雖然支持各種場見場景,但并不是每一種都同樣好用。數(shù)據(jù)流的實(shí)時(shí)處理就是其中相對(duì)較弱的一環(huán)。Flink 憑借更優(yōu)的流處理引擎,同時(shí)也支持各種處理場景,成為 Spark 的有力挑戰(zhàn)者。
Spark 和 Flink 是怎么做到這些的,它們之間又有那些異同,下面我們來具體看一下。
這一部分主要著眼于 Spark 和 Flink 引擎的架構(gòu)方面,更看重架構(gòu)帶來的潛力和限制?,F(xiàn)階段的實(shí)現(xiàn)成熟度和局限會(huì)在后續(xù)生態(tài)部分探討。
要理解 Spark 和 Flink 的 引擎特點(diǎn),首先從數(shù)據(jù)模型開始。
Spark 的數(shù)據(jù)模型是彈性分布式數(shù)據(jù)集 RDD(Resilient Distributed Datasets)。 比起 MapReduce 的文件模型,RDD是一個(gè)更抽象的模型,RDD 靠血緣(lineage) 等方式來保證可恢復(fù)性。很多時(shí)候RDD可以實(shí)現(xiàn)為分布式共享內(nèi)存或者完全虛擬化(即有的中間結(jié)果 RDD 當(dāng)下游處理完全在本地時(shí)可以直接優(yōu)化省略掉)。這樣可以省掉很多不必要的I/O,是早期 Spark 性能優(yōu)勢的主要原因。
Spark 用 RDD 上的變換(算子)來描述數(shù)據(jù)處理。每個(gè)算子(如 map,filter,join)生成一個(gè)新的 RDD。所有的算子組成一個(gè)有向無環(huán)圖(DAG)。Spark 比較簡單地把邊分為寬依賴和窄依賴。上下游數(shù)據(jù)不需要 shuffle 的即為窄依賴,可以把上下游的算子放在一個(gè)階段(stage) 里在本地連續(xù)處理,這時(shí)上游的結(jié)果 RDD可以 省略。下圖展示了相關(guān)的基本概念。更詳細(xì)的介紹在網(wǎng)上比較容易找到,這里就不花太多篇幅了。
Spark DAG(來源:http://datastrophic.io/core-concepts-architecture-and-internals-of-apache-spark/)
Flink 的基本數(shù)據(jù)模型是數(shù)據(jù)流,及事件(Event) 的序列。數(shù)據(jù)流作為數(shù)據(jù)的基本模型可能沒有表或者數(shù)據(jù)塊直觀熟悉,但是可以證明是完全等效的。流可以是無邊界的無限流,即一般意義上的流處理。也可以是有邊界的有限流,這樣就是批處理。
Flink 用數(shù)據(jù)流上的變換(算子)來描述數(shù)據(jù)處理。每個(gè)算子生成一個(gè)新的數(shù)據(jù)流。在算子,DAG,和上下游算子鏈接(chaining) 這些方面,和 Spark 大致等價(jià)。Flink 的節(jié)點(diǎn)(vertex)大致相當(dāng)于Spark 的階段(stage),劃分也會(huì)和上圖的 Spark DAG 基本一樣。
(來源: https://databricks.com/spark/about )
實(shí)時(shí)數(shù)據(jù)流處理和批處理主要區(qū)別就是對(duì)低延時(shí)的要求。Spark 因?yàn)?RDD 是基于內(nèi)存的,可以比較容易切成較小的塊來處理。如果能對(duì)這些小塊處理得足夠快,就能達(dá)到低延時(shí)的效果。
交互式查詢場景,如果數(shù)據(jù)能全在內(nèi)存,處理得足夠快的話,就可以支持交互式查詢。
從這些可以看出來,比起 Hadoop MapReduce, Spark 本質(zhì)上就是基于內(nèi)存的更快的批處理。然后用足夠快的批處理來實(shí)現(xiàn)各種場景。
Flink 中的狀態(tài)支持 (來源:https://www.slideshare.net/ParisCarbone/state-management-in-apache-flink-consistent-stateful-distributed-stream-processing)
一般在流處理的時(shí)候會(huì)比較關(guān)注有狀態(tài)處理,但是仔細(xì)看的話批處理也是會(huì)受到影響的。比如常見的窗口聚合,如果批處理的數(shù)據(jù)時(shí)間段比窗口大,是可以不考慮狀態(tài)的,用戶邏輯經(jīng)常會(huì)忽略這個(gè)問題。但是當(dāng)批處理時(shí)間段變得比窗口小的時(shí)候,一個(gè)批的結(jié)果實(shí)際上依賴于以前處理過的批。這時(shí),因?yàn)榕幚硪嬉话銢]有這個(gè)需求不會(huì)有很好的內(nèi)置支持,維護(hù)狀態(tài)就成為了用戶需要解決的事情。比如窗口聚合的情況用戶就要加一個(gè)中間結(jié)果表記住還沒有完成的窗口的結(jié)果。這樣當(dāng)用戶把批處理時(shí)間段變短的時(shí)候就會(huì)發(fā)現(xiàn)邏輯變復(fù)雜了。這是早期 Spark Streaming 用戶 經(jīng)常碰到的問題。直到 Structured Streaming 出來才得到緩解。
而像 Flink 這樣以流處理為基本模型的引擎,因?yàn)橐婚_始就避不開這個(gè)問題,所以引入了 managed state 來提供了一個(gè)通用的解決方案。比起用戶實(shí)現(xiàn)的特定解決方案,不但用戶開發(fā)更簡單,而且能提供更好的性能。最重要的是能更好地保證處理結(jié)果的一致性。
簡單來說,就是有一些內(nèi)秉的數(shù)據(jù)處理邏輯,在批處理中容易被忽略或簡化處理掉也能得到可用的結(jié)果,而在流處理中問題被暴露出來解決掉了。所以流計(jì)算引擎用有限流來處理批在邏輯上比較嚴(yán)謹(jǐn),能自然達(dá)到正確性。主要做一些不同的實(shí)現(xiàn)來優(yōu)化性能就可以了。而用更小的批來模擬流需要處理一些以前沒有的問題。當(dāng)計(jì)算引擎還沒有通用解決方案的時(shí)候就需要用戶自己解決了。類似的問題還有維表的變化(比如用戶信息的更新),批處理數(shù)據(jù)的邊界和遲到數(shù)據(jù)等等。
Spark 1.6 時(shí)的API狀態(tài)
Spark 的初衷之一就是用統(tǒng)一的編程模型來解決用戶的各種需求。在這方面一直很下功夫。最初基于 RDD 的 API 就可以做各種類型的數(shù)據(jù)處理。后來為了簡化用戶開發(fā),逐漸推出了更高層的DataFrame(在 RDD 中加了列變成結(jié)構(gòu)化數(shù)據(jù))和 Datasets(在 DataFrame 的列上加了類型),并在Spark 2.0 中做了整合(DataFrame = DataSet[Row])。Spark SQL 的支持也比較早就引入了。在加上各個(gè)處理類型API 的不斷改進(jìn),比如 Structured Streaming 以及和機(jī)器學(xué)習(xí)深度學(xué)習(xí)的交互,到了今天Spark 的 API 可以說是非常好用的,也是 Spark 最強(qiáng)的方面之一。
Flink API (來源:https://ci.apache.org/projects/flink/flink-docs-release-1.5/concepts/programming-model.html)
Spark 和 Flink 都是通用的能夠支持超大規(guī)模數(shù)據(jù)處理,支持各種處理類型的計(jì)算引擎。兩個(gè)系統(tǒng)都有很多值得探討的方面在這里沒有觸及,比如 SQL 的優(yōu)化,和機(jī)器學(xué)習(xí)的集成等等。這里主要是試圖從最基本的架構(gòu)和設(shè)計(jì)方面來比較一下兩個(gè)系統(tǒng)。因?yàn)樯蠈拥墓δ茉谝欢ǔ潭壬鲜强梢曰ハ嘟梃b的,有足夠的投入應(yīng)該都能做好。而基本的設(shè)計(jì)改變起來會(huì)傷筋動(dòng)骨,更困難一些。
Spark 和 Flink 的不同執(zhí)行模型帶來的最大的區(qū)別應(yīng)該還是在對(duì)流計(jì)算的支持上。最開始的 Spark Streaming 對(duì)流計(jì)算想得過于簡單,對(duì)復(fù)雜一點(diǎn)的計(jì)算用起來會(huì)有不少問題。從 Spark 2.0 開始引入的 Structured Streaming 重新整理了流計(jì)算的語義,支持按事件時(shí)間處理和端到端的一致性。雖然在功能上還有不少限制,比之前已經(jīng)有了長足的進(jìn)步。不過 micro batch 執(zhí)行方式帶來的問題還是存在,特別在規(guī)模上去以后性能問題會(huì)比較突出。最近 Spark 受一些應(yīng)用場景的推動(dòng),也開始開發(fā)持續(xù)執(zhí)行模式。2.3里的實(shí)驗(yàn)性發(fā)布還只支持簡單的 map 類的操作。
Spark 持續(xù)執(zhí)行模式狀態(tài)(來源:https://www.slideshare.net/databricks/continuous-processing-in-structured-streaming-with-jose-torres)
從最近 Spark+AI Summit 大會(huì)上的介紹來看(下圖),會(huì)發(fā)展成一個(gè)和 Flink 的流處理模式比較相似的執(zhí)行引擎。不過從下圖來看,主要的功能都還在開發(fā)中或者待開發(fā)。對(duì)將來能做到什么程度,和 Spark 原來的 batch 執(zhí)行引擎怎么結(jié)合,我們拭目以待。