大規(guī)模數(shù)據(jù)處理技術如果從MapReduce論文算起,已經(jīng)前后跨越了十六年。我們先沿著時間線看一下大規(guī)模數(shù)據(jù)處理的重要技術和它們產(chǎn)生的年代。后面從MapReduce到Spark、Flink的演進特性來看大規(guī)模數(shù)據(jù)處理計算引擎應該具備什么樣的能力。
[圖片上傳失敗...(image-6ebadf-1561816697086)]
如果參考人類發(fā)展史的劃分,我們大概可以把大規(guī)模數(shù)據(jù)處理技術的演進劃分為五個階段:石器時代,青銅時代,鐵器時代、蒸汽時代、電氣時代。每個時代的演進都具有顯著的意義。(當然我們這里只討論大數(shù)據(jù)處理中偏MapReduce派系分支的計算引擎處理)
大規(guī)模數(shù)據(jù)處理的技術的五個時代和四代引擎
- 石器時代
隨著互聯(lián)網(wǎng)的蓬勃發(fā)展,數(shù)據(jù)量在呈指數(shù)型增長。早在2003年之前,各大廠商都已經(jīng)嚴重面臨大規(guī)模數(shù)據(jù)的處理難題,比如Google就已經(jīng)面對大于600億的搜索量。如何從海量的原始數(shù)據(jù)中挖掘出有效的信息,如何保證數(shù)據(jù)挖掘程序的容錯性一直困擾著Google的工程師們。
這個時候大規(guī)模數(shù)據(jù)處理技術還處于仿徨階段,每個公司甚至個人都有一套獨立的數(shù)據(jù)處理工具,層次不齊,紛繁復雜,但是還沒有提煉抽象出一個系統(tǒng)的辦法。
- 青銅時代
直到2003年,MapReduce問世,開啟了數(shù)據(jù)處理的青銅時代(真正意義上的第一代大數(shù)據(jù)計算引擎)。Jeff Dean和Sanjay Ghemawat發(fā)表革命性的論文MapReduce:Simplified Data Processing on Large Clusters,從紛繁復雜的業(yè)務邏輯中抽象出Map和Reduce這樣足夠通用的編程模型。利用這個簡單的編程模型編寫分布式程序,跑在那些廉價的機器上。在隨后的十年中,MapReduce在Google內(nèi)部廣泛使用,不斷優(yōu)化,投入了大量的人力物力將這套系統(tǒng)推向了前所未有的高度。
- 鐵器時代
MapReduce雖好,但是對于上層應用來說,在一些復雜的應用場景下,編寫MapReduce程序會變得越來越復雜,工程師們想法設法的拆分算法,實現(xiàn)多個Job的串聯(lián),開發(fā)維護工作量大。這種弊端催生了DAG(有向無環(huán)圖)框架的誕生,支持DAG的框架被劃分為第二代計算引擎,如Tez以及Ooize,此時計算引擎處理的大多數(shù)都還是批處理任務。
- 蒸汽機時代
時代的步伐并不會滿足于計算引擎的一點點進步,計算時間太長的問題一直被詬病。直到基于分布式內(nèi)存的Spark作為第三代計算引擎出現(xiàn),才逐漸取代了MapReduce的龍頭地位(2014年之后,國際各大互聯(lián)網(wǎng)廠商幾乎都沒有人再直接寫MapReduce程序了),并且逐步向流處理開始發(fā)力。第三代計算引擎的出現(xiàn),促進了上層應用快速發(fā)展,如各種迭代計算以及流計算和SQL等。
- 電氣時代
隨著時代的前行,上層應用越來越注重實時流處理技術,以及批流一體化的計算引擎框架。這時批流一體化的新貴Flink應運而生;同時Spark也在不斷彌補自己在實時流處理上的短板,增加新特性;而Google也在不斷發(fā)力,推出Apache Beam。師夷長技以制夷,各大計算引擎相互參考,不斷優(yōu)化著自己的短板,推出新的特性,爭當?shù)谒拇嬎阋婵钙焓帧?/p>
如果重登歷史的巨輪,一路走馬觀花般地來看看大數(shù)據(jù)處理計算引擎的每一個轉(zhuǎn)折點,我們不難發(fā)現(xiàn)每一次的升級都是在業(yè)務和技術開發(fā)的雙重推動下穩(wěn)步前行,每一次升級都是對數(shù)據(jù)模型抽象能力的提升。那么,我們不禁思考,下一代(第四代)計算引擎應該具備什么樣的能力?回答這個問題前,我們先來看看每一代計算引擎都有什么問題?
歷代計算引擎的問題和創(chuàng)新點
MapReduce
首先從第一代計算引擎開始。MapReduce雖好,但飲者不會貪杯。不可否認,作為劃時代的一筆,MapReduce解決了當時大規(guī)模數(shù)據(jù)處理的大部分問題。但是其由于某些問題,依舊被開發(fā)者詬?。?/p>
- 開發(fā)復雜度高,只提供了Map和Reduce兩個操作
- MapReduce 模型的抽象層次低,大量的底層邏輯都需要開發(fā)者手工完成。開發(fā)者在使用MapReduce的時候,需要嚴格的遵循Map和Reduce步驟,當構造更為復雜的處理架構時,往往需要協(xié)調(diào)多個Map和多個Reduce任務。很多現(xiàn)實的處理場景并不適合用這個模型來描述。
- 高昂的維護成本
- 程序每一步的MapReduce都可能出錯,為了處理這些異常,很多人開始設計自己的協(xié)調(diào)系統(tǒng)和容錯系統(tǒng),比如做一個狀態(tài)機來協(xié)調(diào)多個MapReduce任務,這樣大大增加了整個系統(tǒng)的復雜度。(如果你Google一下“MapReduce orchestration”關鍵字,你會發(fā)現(xiàn)很多書整篇都在講如何協(xié)調(diào)MapReduce任務)
- 配置太復雜,錯誤的配置最終導致數(shù)據(jù)
- 實際的開發(fā)過程中,不是每個人都對MapReduce細微的配置信息了如指掌,對一個沒有用過MapReduce的新手來說是很難發(fā)揮好MapReduce的性能的。(Google有500多頁的關于MapReduce的性能調(diào)優(yōu)的說明手冊,可見其復雜度之高)
- 調(diào)優(yōu)的過程也比較漫長。Google曾在2007年到2012年間做過一個對于1PB數(shù)據(jù)的大規(guī)模排序,來測試MapReduce的性能?;宋迥陼r間從12小時優(yōu)化到0.5個小時,包括緩沖大小,分片多少,預抓取策略,緩存大小等等。
- 計算效率低
- 每一個Job的計算結(jié)果都會存儲在HDFS文件系統(tǒng)中,每一步的計算都需要進行硬盤的讀寫和寫入,大大增加了系統(tǒng)的的延遲。所以MapReduce對于迭代算法的處理性能很差,而且很耗資源。
- MapReduce只支持數(shù)據(jù)批處理,應對流處理的時候不再得心應手
- 真正的業(yè)務系統(tǒng),批處理和流處理常常是混合共生,或者頻繁切換的。
MapReduce作為分布式數(shù)據(jù)處理的開山鼻祖,雖然有很多缺陷,但是它的思想不僅沒有過時,而且還影響了新的數(shù)據(jù)處理系統(tǒng)的設計,如Spark,Storm,Presto,Impala等。
傳統(tǒng)的MapReduce任務之所以運行速度慢,主要是由于需要將計算的中間結(jié)果落地到硬盤這種穩(wěn)定的存儲介質(zhì)中來防止運行結(jié)果丟失,每一次獲取中間結(jié)果,都需要進行一次硬盤的讀取,反復讀寫操作以及潛在的數(shù)據(jù)復制和序列化操作大大的提高了計算的延遲。
Tez
作為第二代計算引擎的代表Tez是一個運行在Yarn上支持DAG(有向無環(huán)圖)作業(yè)的計算框架,是對MapReduce數(shù)據(jù)處理的歸納。它把Map/Reduce過程拆分成若干個子過程,同時可以把多個Map/Reduce任務組合成一個較大的DAG任務,減少了Map/Reduce之間的文件存儲。同時合理組合其子過程,也可以減少任務的運行時間。Tez的問世解決了MapReduce開發(fā)復雜度高,計算效率低的問題。
但Tez并不直接面向最終用戶,事實上它允許開發(fā)者為最終用戶構建性能更快、擴展性更好的應用程序。但Tez的目的主要是幫助Hadoop處理很多需要近實時查詢、機器學習的用例場景。
Spark
作為第三代計算引擎的Spark幾乎解決了上面列出的MapReduce面臨的所有問題。
相較與MapReduce的數(shù)據(jù)模型,Spark提出了另外一種基于分布式內(nèi)存的基本數(shù)據(jù)抽象模型RDD(彈性分布式數(shù)據(jù)集:表示已被分區(qū)、不可變的,并能夠被并行操作的數(shù)據(jù)集合),在各方面都有很大的提升,同時保證了系統(tǒng)的穩(wěn)定性、錯誤恢復和可拓展性,并且盡可能的減少磁盤I/O操作。
- 首先,它盡可能的把數(shù)據(jù)存在內(nèi)存中,大大的提高了數(shù)據(jù)處理的效率;
- 其次,它是分區(qū)存儲,天然支持并行處理
- 它存儲了每一步驟計算結(jié)果之間的依賴關系,大大提升了數(shù)據(jù)容錯性和錯誤恢復的正確率,是Spark更加可靠
與編寫MapReduce程序一樣,針對RDD的編程還是比較偏向于底層,然而我們并不是總需要在RDD的層次進行編程,同樣針對RDD的編程需要開發(fā)人員手動進行性能調(diào)優(yōu)。幸運的是Spark生態(tài)系統(tǒng)提供了一個高級結(jié)構化數(shù)據(jù)抽象模型和功能模塊,使開發(fā)變得簡單。比如Spark SQL,DataFrame,DataSet。
從發(fā)展歷史角度來看,RDD API是在Spark設計之初就有的,是整個Spark框架的基石。為了方便熟悉數(shù)據(jù)庫和SQL的開發(fā)人員使用,在RDD的基礎上,Spark創(chuàng)建了DataFrame API,開發(fā)人員可以方便的對數(shù)據(jù)的列進行操作。在Spark 1.6中,引入了DataSet,它在DataFrame的基礎上添加了對數(shù)據(jù)每一列的類型的限制。在Spark2.0中,DataFrame和DataSet被統(tǒng)一。DataFrame作為DataSet[Row]存在。
DataSet和DataFrame都是基于RDD的,都擁有RDD的基本特性,但是性能要比RDD更好。是因為Spark程序運行時,Spark SQL的查詢優(yōu)化器會對語句進行分析,生成優(yōu)化過的RDD在底層執(zhí)行。基于DataFrame和DataSet API開發(fā)的程序會被自動優(yōu)化,使得開發(fā)人員不需要操作底層的RDD API來進行手動優(yōu)化,大大提升開發(fā)效率。(但是 RDD API 對于非結(jié)構化的數(shù)據(jù)處理有獨特的優(yōu)勢,比如文本流數(shù)據(jù),而且方便底層操作。所以在開發(fā)中,還是要根據(jù)實際情況來選擇使用哪種API)
無論是DataFrame API還是DataSet API,都是基于批處理模式對靜態(tài)數(shù)據(jù)進行處理的。當需要對數(shù)據(jù)進行流處理操作時,Spark生態(tài)圈引入了Spark Streaming。
Spark Streaming提供了一個對流數(shù)據(jù)的抽象DStream(由很多個序列化的RDD構成)。DStream可以來自Kafka、Flume或者HDFS的流數(shù)據(jù)生成,也可以由別的DStream經(jīng)過各種轉(zhuǎn)換操作得來。由于Spark Streaming的底層是基于RDD實現(xiàn)的,所以RDD的優(yōu)良特性它都有:
- 數(shù)據(jù)容錯性,如果RDD某些分區(qū)丟失了,可以通過依賴信息重新計算恢復
- 運行速度,DSteam可以通過持久化方法將數(shù)據(jù)流放在內(nèi)存中,在遇到需要多次迭代計算的程序中,速度優(yōu)勢十分明顯
- 作為Spark生態(tài)的一部分,可以和Spark核心引擎、Spark SQL、MLib無縫銜接
但是Spark Streaming由于不支持太小的批處理時間間隔而帶來的秒級別計算延遲,在實時性要求比較高的場景下被詬病。所以引申出了Structured Streaming。
- Spark Streaming提供的DStream API與RDD API比較類似,相對比較低level,前面已經(jīng)提到RDD API開發(fā)的程序需要開發(fā)者自己構造RDD的DAG執(zhí)行圖,依賴開發(fā)者自己去優(yōu)化。既然Spark已經(jīng)提供了DataFrame,DataSet這種高級API,可以自動優(yōu)化Spark程序了,那么能否將他們應用在流處理中呢?答案是肯定的。2016年,Spark在2.0版本中推出了結(jié)構化流數(shù)據(jù)處理模塊Structured Streaming。Structured Streaming是基于Spark SQL引擎實現(xiàn)的,依賴Spark Streaming,在開發(fā)者眼里,流數(shù)據(jù)和靜態(tài)數(shù)據(jù)是沒有區(qū)別的,開發(fā)者可以像處理批處理靜態(tài)數(shù)據(jù)那樣去處理流數(shù)據(jù)。隨著流數(shù)據(jù)的持續(xù)輸入,借助于Spark SQL的優(yōu)化引擎,Spark SQL引擎會幫助我們持續(xù)地處理新數(shù)據(jù),更新計算結(jié)果。所以Structured Streaming的應用程序性能很好。(現(xiàn)在Spark社區(qū)幾乎停止了關于Spark Streaming的更新,將重心投放到Structured Streaming上了)。
- 實時性,其次Spark Streaming是準實時的,它能做到最小延遲在一秒左右,雖然Structured Streaming的思想類似,但是相比Spark Streaming來說,它能做到更小的時間間隔,最小延遲在100毫秒左右,在Spark2.3版本中。Structured Streaming引入了連續(xù)處理模式,可以做到真正的毫秒級延遲,拓展了Structured Streaming的應用廣度。
- 對事件時間的支持,Spark Streaming把數(shù)據(jù)接收到的時間切分成一個個RDD進行批處理,所以它很難基于數(shù)據(jù)本省的產(chǎn)生時間來進行處理。而Structured Streaming對基于事件時間的處理有很好的支持。
- Structured Streaming還有其它優(yōu)點,比如它有更好的容錯性,保證了端到端的exactly once語義等
無論是Spark Streaming還是Structured Streaming,Spark流處理的實時性還是不夠,所以還是無法用在一些對實時性要求很高的流處理場景中,這是因為Spark的流處理是基于微批處理的思想,它把流處理看做批處理的一種特殊形式,每次收到一個時間間隔的數(shù)據(jù)才會去處理,所以天生很難在實時性上有所提升,雖然Spark 2.3提出了連續(xù)處理模型,但是支持功能有限,還有很長的路要走。
Flink
想要在流處理的實時性上提升,就不能繼續(xù)用微批處理的模式,要做到每當有一條數(shù)據(jù)輸入就立即處理,不做等待。Flink就是這方面的翹楚,它采用基于操作符的連續(xù)流模型,可以做到微秒級別的延遲。
Flink中最核心的數(shù)據(jù)結(jié)構Stream,它代表一個運行在多個分區(qū)上的并行流,與Spark的RDD不同的是,Stream代表一個數(shù)據(jù)流而不是靜態(tài)數(shù)據(jù)的集合,它包含的數(shù)據(jù)是隨著時間增長變化的。
Flink提供兩個核心API:用于做批處理的DataSet API和和流處理的Data Stream API。
Flink和Spark都有很多相同點:
- 都基于內(nèi)存計算
- 都有統(tǒng)一的批處理和流處理API,都支持類似SQL的編程接口
- 都支持很多相同的轉(zhuǎn)換操作,編程都是類似于Scala Collection API的函數(shù)式編程模式
- 都有完善的錯誤恢復機制
- 都支持Exactly once的語義一致性
當然也有很多不同點:
- 從流處理的角度來講,Spark是基于微批處理,把流數(shù)據(jù)看成一個個小的批處理數(shù)據(jù)塊分別處理,延遲性只能做到秒級。Flink基于每個時間處理,每當有新的數(shù)據(jù)輸入都會立即處理,是真正的流式計算,支持毫秒級計算?;谕瑯拥脑颍琒park只能支持基于時間的窗口操作(處理時間或者事件時間),而Flink支持的窗口操作非常靈活,不僅支持時間窗口,還支持基于數(shù)據(jù)本身的窗口,開發(fā)者可以自定義想要的窗口操作
- 從SQL功能的角度來講,Spark和Flink分別提供SparkSQL和Table API提供的SQL交互支持。相比而言,Spark SQL支持更好,相應的優(yōu)化、拓展和性能更好,F(xiàn)link在這方面還有很大提升空間
- 從機器學習迭代計算的角度來講,Spark對機器學習的支持很好,可以在內(nèi)存中緩存中間計算結(jié)果加速機器學習算法的運行。但是大部分機器學習算法其實是一個有環(huán)的數(shù)據(jù)流,然而Spark是用無環(huán)圖來標示的。Flink支持在運行時間總的有環(huán)數(shù)據(jù)流,從而可以更有效的對機器學習算法進行運行
- 從生態(tài)系統(tǒng)角度來講,Spark的社區(qū)更加活躍,Spark有著Apache旗下最多的開源貢獻者,有很多不同的庫用在不同場景。Flink比較新,社區(qū)活躍度不如Spark活躍,各種庫的功能不如Spark全面。但是Flink在國內(nèi)背后有阿里、華為、美團的加持,相信這塊這后面會不斷完善。
Beam
在Spark和Flink分別發(fā)力爭當下一代計算引擎的領頭羊時,來自大洋彼岸的Google發(fā)出了自己的聲音。2016年,Google聯(lián)合Talend、Cloudera等大數(shù)據(jù)公司,基于Dataflow Model思想開發(fā)出一套SDK,Apache Beam(Batch + Streaming),其含義就是統(tǒng)一了批處理和流處理的一個框架。
Beam提供了一套統(tǒng)一的API來處理這兩種數(shù)據(jù)處理模式,開發(fā)者只需要專注于在數(shù)據(jù)處理的算法上,不用花時間去對兩種數(shù)據(jù)處理模式的差異進行維護。它將工程師寫的算法邏輯和底層運行的環(huán)境分隔開,即使用Beam提供的API寫好數(shù)據(jù)處理邏輯后,這個邏輯可以不做任何修改,直接放到任何支持Beam API的底層系統(tǒng)上運行,如Google Cloud Dataflow,F(xiàn)link,Spark等。在Beam上,這些底層運行的系統(tǒng)被稱為Runner,Beam提供了Java、Python、Golang的SDK,支持多語言編寫程序。(熟悉深度學習的朋友可以把Beam理解為Keras,它編寫的程序可以運行在TensorFlow、Theano、CNTK這些backends上,或者把Beam理解成SQL,它編寫的程序就是Query,這個Query可以放在任何數(shù)據(jù)庫系統(tǒng)上運行,比如Mysql或者Oracle上)
Apache Beam和其它開源項目不太一樣,它不是一個數(shù)據(jù)處理平臺,本身無法對數(shù)據(jù)進行處理。Beam所提供的是一個統(tǒng)一的編程思想,通過這個統(tǒng)一的借口編寫符合各自需求的處理邏輯,這些處理邏輯被轉(zhuǎn)換為底層引擎相應的API去運行(是有一定的性能損耗的)。Beam的編程模型會涉及到4個概念:窗口、水印、觸發(fā)器和累加模式
- 窗口(Window):窗口將無邊界的數(shù)據(jù)更具時間實踐分成了一個個有限的數(shù)據(jù)集
- 水印(Watermark):用來表示與數(shù)據(jù)事件時間相關聯(lián)的輸入完整性的概念。在數(shù)據(jù)處理中,水印是用來測量數(shù)據(jù)進度的。對于事件時間為X的水印表示數(shù)據(jù)處理邏輯已經(jīng)得到了所有事件時間小于X的無邊界數(shù)據(jù)
- 觸發(fā)器(Triggers):表示具體在什么時候,數(shù)據(jù)處理邏輯會真正的觸發(fā)窗口中的數(shù)據(jù)倍計算。
- 累加模式(Accumulation):如果我們在同一個窗口中得到多個運算結(jié)果,如何處理這些運行結(jié)果,是丟棄、追加,還是直接覆蓋
大規(guī)模數(shù)據(jù)處理計算引擎該有的樣子
世界上最好的樣子,莫過于我喜歡的樣子,你都有。 ---徐志摩沒有說過
歷史的篇章就翻到這里。讓我們回到最初的問題:新一代的計算引擎應該具備什么樣的能力?其實從Spark的發(fā)展旅程和Flink、Beam的特性,不難發(fā)現(xiàn)一些基本的雛形,下面站在工程師的角度來簡單歸納一下:
-
編程簡單,易維護:你需要提供一種讓多步驟數(shù)據(jù)處理變得易于維護抽象技術
- 作為工程師的我們或許可以用有向無環(huán)圖(DAG)來抽象表達。因為有向圖能為多個步驟的數(shù)據(jù)處理依賴關系,建立很好的模型。
- 支持SQL語言?,F(xiàn)在機器學習都能SQL化了,Kakfa也能SQL化了,能一行SQL解決的問題,為什么還要去寫多行代碼?
- 支持多語言的客戶端
- 自優(yōu)化:你已經(jīng)是一個成熟的計算引擎了,我不想要復雜的配置,你需要能自動進行性能優(yōu)化
-
業(yè)務邏輯描述和計算分離:你可以把數(shù)據(jù)處理的描述語言,與背后的運行引擎解耦合開來
- 在使用有向無環(huán)圖進行數(shù)據(jù)抽象描述之后,數(shù)據(jù)處理描述語言部分已經(jīng)可以和運算引擎部分分離了。有向圖可以作為數(shù)據(jù)處理描述語言和運算引擎的前后端分離協(xié)議。
- 業(yè)務團隊可以使用不用語言的客戶端進行數(shù)據(jù)描述,計算引擎由C++實現(xiàn),由數(shù)據(jù)底層團隊維護并高度優(yōu)化
- 數(shù)據(jù)描述可以在本地寫,計算引擎在云端執(zhí)行
-
批流一體化:你要提供統(tǒng)一批處理和流處理的編程模型,我不想再寫兩套代碼了
- 批處理處理的是有界離散的數(shù)據(jù),比如處理一個文本文件;流處理處理的是無界連續(xù)的數(shù)據(jù),比如每時每刻的支付寶交易數(shù)據(jù)。
- 真正的業(yè)務系統(tǒng),批處理和流處理常常是混合共生,或者頻繁切換的
- 不論是批處理還是流處理的,都用統(tǒng)一的數(shù)據(jù)結(jié)構表示。編程的API也需要統(tǒng)一。不論業(yè)務需求怎么樣,開發(fā)者只需要學習一套API
-
自監(jiān)控:你要在架構層面提供異常處理和數(shù)據(jù)監(jiān)控的能力,對數(shù)據(jù)處理的每一步提供自動的監(jiān)控平臺
- 做過大規(guī)模數(shù)據(jù)處理系統(tǒng)的人都很明白:一個復雜的數(shù)據(jù)處理系統(tǒng)中,難的不是開發(fā)系統(tǒng),而是異常處理。
- 下一代大規(guī)模數(shù)據(jù)處理框架要有一套基本的數(shù)據(jù)監(jiān)控能力,對于數(shù)據(jù)處理的每一步提供自動的監(jiān)控平臺
題外話
題外話1: Spark SQL
- 在那個MapReduce橫行的時代,大部分開發(fā)人員最熟悉的還是傳統(tǒng)的關系型數(shù)據(jù)庫,MapReduce的開發(fā)對于他們來講使用難度較大,所以Hive就應運而生了,Hive提供類似SQL的編程接口,HQL語句經(jīng)過語法解析、邏輯計劃、物理計劃轉(zhuǎn)換成MapReduce程序運行,使開發(fā)人員很容易對HDFS上存儲的數(shù)據(jù)進行查詢和分析。
- Spark剛問世的時候,也開發(fā)了一個Shark來支持SQL語言查詢,它的本質(zhì)是Hive,修改了Hive的內(nèi)存管理模塊,大幅度優(yōu)化了運行速度,是Hive的10-100倍。但是Shark對于Hive的依賴嚴重影響了Spark的發(fā)展。Spark想要的不只是一個SQL,而是想要定義一個統(tǒng)一的技術棧和完整的生態(tài),眼睛里面揉不得沙子的Spark不可能允許有這樣的外在依賴,所以就將Shark交給Hive進行管理,轉(zhuǎn)而開發(fā)SparkSQL
- 摒棄了Shark將SQL語句轉(zhuǎn)化為Spark RDD的執(zhí)行引擎,就想脫韁的野馬一樣跑的“飛快”。Spark SLQ不僅將關系型數(shù)據(jù)庫的處理模式和Spark的函數(shù)式編程相結(jié)合,還兼容了Hive、RDD、JSON、CSV等多種數(shù)據(jù)格式
題外話2:流處理計算的技術選型
看起來Flink在數(shù)據(jù)處理這塊的能力完爆Spark,但是在下列場景下,Spark更加適合,Spark可以一站式解決這些問題,無需其他的數(shù)據(jù)處理平臺:
- 數(shù)據(jù)量非常大而且邏輯復雜的批數(shù)據(jù)處理,并且對計算效率有較高要求(比如個性化推薦、廣告精準營銷)
- 基于歷史數(shù)據(jù)的交互式查詢,要求相應較快
- 基于實時數(shù)據(jù)量的數(shù)據(jù)處理,延遲性要求在數(shù)百毫秒到數(shù)秒之間
題外話3:流處理計算編程模型 WWWH
- What result are calculated?*: 我們要計算什么?比如經(jīng)典例子WordCount就是要計算每個詞出現(xiàn)的次數(shù)
- Where in event time are calculated?: 計算什么時間范圍的數(shù)據(jù)?一般通過窗口來表示,比如計算的一點兩點的訪問量
- When in processing are result materialized?: 何時將計算結(jié)果輸出?可以通過水印和觸發(fā)器配合觸發(fā)計算。可根據(jù)時間信號或者窗口元素計數(shù)來觸發(fā),比如定義好固定窗口為1個小時,元素個數(shù)為10,從凌晨0:00開始,每當1:00,2:00或者窗口內(nèi)個數(shù)超過10時,就會觸發(fā)計算將結(jié)果輸出
- How do refinement of result related?: 后續(xù)數(shù)據(jù)處理結(jié)果如何影響之前的處理結(jié)果?這個可以通過累加模式解決(丟棄,累積)
題外話4:Apache Beam
Apache Beam最早來自于Google內(nèi)部產(chǎn)生的FlumeJava。在Google內(nèi)部,基于前面提到的關于MapReduce的各種問題,Google的工程師們開始考慮如何解決那些問題,F(xiàn)lumeJava在這樣的背景下誕生了,并且在2010的時候公開了其論文FlumeJava: Easy, Efficient Data-Parallel Pipelines.
FlumeJava的思想是將所有的數(shù)據(jù)都抽象為一個叫PCollection的數(shù)據(jù)結(jié)構,在Map和Reduce的思想上,抽象出了4個原始操作:parallelDo, groupByKey, combineValues和flatten,這4種原始操作能表達任意Map或者Reduce邏輯,同時它采用了一種Deferred Evalution的技術(遍歷靜態(tài)代碼,構建一個可執(zhí)行的有向無環(huán)圖,有了圖之后就可以很好的優(yōu)化代碼)來優(yōu)化開發(fā)寫的代碼。
但是FlumeJava有一個弊端,就是只能支持批處理的任務,對于流處理的框架卻是來自另外一個項目MillWheel: Fault-Tolerant Stream Processing at Internet Scale。Google的工程師能回頭一看,優(yōu)秀,但是貌似我們可以再優(yōu)秀一點,于是集合多個框架(包括MapReduce)的Dataflow Model誕生了The Dataflow Model: A Practical Approach to Balancing Correctness, Latency, and Cost in Massive-Scale, Unbounded, Out-of-Order Data Processing。
但是Dataflow Model的程序需要運行在Google的云平臺上,如何才能在其它的平臺商跑起來呢,所以為了解決這個問題,才有了Apache Beam的誕生
題外話5: 個人解讀一下現(xiàn)在計算引擎發(fā)展的趨勢
首先統(tǒng)一計算平臺和批流一體化已經(jīng)是主要趨勢了。
對于Spark來說,它是很優(yōu)秀的一個引擎,依靠強大的社區(qū)、生態(tài)圈、all in one的組件棧,占據(jù)大部分的市場。從Spark2.3 Structured streaming出來后的批流api的統(tǒng)一,以及目前在不斷的優(yōu)化continues Mode,可以看出Spark在逐漸彌補自己實時流處理計算的短板。此外Spark還引入第四種調(diào)度策略Kubernetes clusters集成如火如荼的云平臺設施;引入并且不斷改善pandas的性能來提升PySpark讓很多重度依賴pandas的數(shù)據(jù)分析師得心應手;以及對深度學習的支持??梢哉fSpark的棋盤鋪的很大,想法設法的討開發(fā)者的喜愛。所以這也是我不太認可現(xiàn)在大部分道友認為Flink已經(jīng)是下一代計算引擎的領頭羊的這個觀點,憑借Spark這些中盤的布局,在收官階段未必沒有和Flink的一拼之勢。
而Flink,的確因為阿里的運營,在國內(nèi)火了。但也展現(xiàn)了它的獨有優(yōu)勢,更加貼近dataflow model的思想。同時,基于社區(qū)以及阿里、華為小伙伴的努力,flink的table/sql 的api也得到的很大的增強,提供了批流統(tǒng)一的api。雖然底層需要分化為dataset和datastream以及runtime層的batchTask和StreamTask,但是現(xiàn)在也在rethink the stack,這個點在2019 SF的大會也幾乎吸引了所有人。但就現(xiàn)狀而言,flink的確有著理念上的優(yōu)勢(流是批的超集),同時也有迅猛上升的趨勢。同時Flink也有自己的機器學習庫(FlinkML)和圖分析庫(Gelly),以及強大的復雜時間處理庫(CEP)??傊甋park有的,他全都要,F(xiàn)link想要的,可不僅僅只是一個流計算而已。
再來看看Beam,不可否認Beam的新穎性和所站的高度,憑借Google的背書,或許以后的應用面特別廣,但在國內(nèi)要大面積的接受采納接受的話,大概還需要四五年的樣子。而且Beam只是對批流處理進行了抽象一體化,計算還是要依賴其它計算引擎,目前對SQL,Machine Learning的支持也不是很完善(但我覺得Google要想要支持也是很容易,特別和其它計算框架如TensorFlow等結(jié)合起來,這畫面太美不敢看)。但Beam提出的抽象模式很值得我們借鑒,不僅僅只是應用在數(shù)據(jù)處理方面。