王海濤,曾經在微軟的 SQL Server和大數據平臺組工做多年。帶領團隊創建了微軟對內的 Spark 服務,主打 Spark Streaming。去年加入阿里實時計算部門,參與改進阿里基於 Apache Flink 的Blink 平臺。html
導讀: 作大數據絕對躲不過的一個熱門話題就是實時流計算,而提到實時流計算,就不得不提 Spark 和 Flink。Spark 從 2014 年左右開始迅速流行,剛推出時除了在某些場景比 Hadoop MapReduce 帶來幾十到上百倍的性能提高外,還提出了用一個統一的引擎支持批處理、流處理、交互式查詢、機器學習等常見的數據處理場景。憑藉高性能和全面的場景支持,Spark 早已成爲衆多大數據開發者的最愛。數據庫
正在 Spark 如日中天高速發展的時候,2016 年左右 Flink 開始進入大衆的視野並逐漸廣爲人知。在人們開始使用 Spark 以後,發現 Spark 雖然支持各類常見場景,但並非每一種都一樣好用。數據流的實時處理就是其中相對較弱的一環。Flink 憑藉更優的流處理引擎,同時也支持各類處理場景,成爲 Spark 的有力挑戰者。固然,Spark 也在不斷加強其實時流處理能力,在今年 2 月份發佈的 2.3 版本中引入了持續流式處理模型,可將流處理延遲下降至毫秒級別。apache
本文對 Spark 和 Flink 的技術與場景進行了全面分析與對比,且看下一代大數據計算引擎之爭,誰主沉浮?編程
自從數據處理需求超過了傳統數據庫能有效處理的數據量以後,Hadoop 等各類基於 MapReduce 的海量數據處理系統應運而生。從2004 年 Google 發表 MapReduce 論文開始,通過近10年的發展,基於 Hadoop 開源生態或者其它相應系統的海量數據處理已經成爲業界的基本需求。api
可是,不少機構在開發本身的數據處理系統時都會發現須要面臨一系列的問題。從數據中獲取價值須要的投入遠遠超過預期。常見的問題包括:網絡
上圖是一個典型的lambda架構,只是包含了批處理和流處理兩種場景,就已經牽涉到至少四五種技術了,還不算每種技術的可替代選擇。再加上實時查詢,交互式分析,機器學習等場景,每一個場景都有幾種技術能夠選擇,每一個技術涵蓋的領域還有不一樣方式的重疊。結果就是一個業務常常須要使用四五種以上的技術才能支持好一個完整的數據處理流程。加上調研選型,須要瞭解的數目還要多得多。架構
下圖是大數據領域的全景。有沒有暈?運維
大數據和 AI 全景 – 2018 (來源: mattturck.com/bigdata2018…開發和運行效率低下。由於牽涉到多種系統,每種系統有本身的開發語言和工具,開發效率可想而知。而由於採用了多套系統,數據須要在各個系統之間傳輸,也形成了額外的開發和運行代價,數據的一致也難以保證。在不少機構,實際上一半以上的開發精力花在了數據在各個系統之間的傳輸上。機器學習
複雜的運維。多個系統,每一個須要本身的運維,帶來更高的運維代價的同時也提升了系統出問題的可能。異步
數據質量難以保證。數據出了問題難以跟蹤解決。
最後,還有人的問題。在不少機構,因爲系統的複雜性,各個子系統的支持和使用落實在不一樣部門負責。
瞭解了這些問題之後,對Spark 從2014年左右開始迅速流行就比較容易理解了。Spark 在當時除了在某些場景比 Hadoop MapReduce 帶來幾十到上百倍的性能提高外,還提出了用一個統一的引擎支持批處理,流處理,交互式查詢,機器學習等常見的數據處理場景。看過在一個 Notebook 裏完成上述全部場景的 Spark 演示,對比以前的數據流程開發,對不少開發者來講不難作出選擇。通過幾年的發展,Spark 已經被視爲能夠徹底取代 Hadoop 中的 MapReduce 引擎。
正在 Spark 如日中天高速發展的時候,2016年左右 Flink 開始進入大衆的視野並逐漸廣爲人知。爲何呢?原來在人們開始使用 Spark 以後,發現 Spark 雖然支持各類場見場景,但並非每一種都一樣好用。數據流的實時處理就是其中相對較弱的一環。Flink 憑藉更優的流處理引擎,同時也支持各類處理場景,成爲 Spark 的有力挑戰者。
Spark 和 Flink 是怎麼作到這些的,它們之間又有那些異同,下面咱們來具體看一下。
這一部分主要着眼於 Spark 和 Flink 引擎的架構方面,更看重架構帶來的潛力和限制。現階段的實現成熟度和侷限會在後續生態部分探討。
要理解 Spark 和 Flink 的 引擎特色,首先從數據模型開始。
Spark 的數據模型是彈性分佈式數據集 RDD(Resilient Distributed Datasets)。 比起 MapReduce 的文件模型,RDD是一個更抽象的模型,RDD 靠血緣(lineage) 等方式來保證可恢復性。不少時候RDD能夠實現爲分佈式共享內存或者徹底虛擬化(即有的中間結果 RDD 當下遊處理徹底在本地時能夠直接優化省略掉)。這樣能夠省掉不少沒必要要的I/O,是早期 Spark 性能優點的主要緣由。
Spark 用 RDD 上的變換(算子)來描述數據處理。每一個算子(如 map,filter,join)生成一個新的 RDD。全部的算子組成一個有向無環圖(DAG)。Spark 比較簡單地把邊分爲寬依賴和窄依賴。上下游數據不須要 shuffle 的即爲窄依賴,能夠把上下游的算子放在一個階段(stage) 裏在本地連續處理,這時上游的結果 RDD能夠 省略。下圖展現了相關的基本概念。更詳細的介紹在網上比較容易找到,這裏就不花太多篇幅了。
Spark DAG(來源: datastrophic.io/core-concep…Flink 的基本數據模型是數據流,及事件(Event) 的序列。數據流做爲數據的基本模型可能沒有表或者數據塊直觀熟悉,可是能夠證實是徹底等效的。流能夠是無邊界的無限流,即通常意義上的流處理。也能夠是有邊界的有限流,這樣就是批處理。
Flink 用數據流上的變換(算子)來描述數據處理。每一個算子生成一個新的數據流。在算子,DAG,和上下游算子連接(chaining) 這些方面,和 Spark 大體等價。Flink 的節點(vertex)大體至關於Spark 的階段(stage),劃分也會和上圖的 Spark DAG 基本同樣。
Flink 任務圖 (來源: ci.apache.org/projects/fl…在 DAG的執行上,Spark 和 Flink 有一個比較顯著的區別。 在Flink 的流執行模式中,一個事件在一個節點處理完後的輸出就能夠發到下一個節點當即處理。這樣執行引擎並不會引入額外的延遲。與之相應的,全部節點是須要同時運行的。而 Spark 的 micro batch 和通常的batch 執行同樣,處理完上游的 stage 獲得輸出以後纔開始下游的 stage。
在Flink的流執行模式中,爲了提升效率也能夠把多個事件放在一塊兒傳輸或者計算。但這徹底是執行時的優化,能夠在每一個算子獨立決定,也不用像 RDD 等批處理模型中同樣和數據集邊界綁定,能夠作更加靈活的優化同時能夠兼顧低延遲需求。
Flink 使用異步的 checkpoint 機制來達到任務狀態的可恢復性,以保證處理的一致性,因此在處理的主流程上能夠作到數據源和輸出之間數據徹底不用落盤,達到更高的性能和更低的延遲。
除了批處理以外,Spark 還支持實時數據流處理,交互式查詢,和機器學習,圖計算等。
(來源: databricks.com/spark/about )實時數據流處理和批處理主要區別就是對低延時的要求。Spark 由於 RDD 是基於內存的,能夠比較容易切成較小的塊來處理。若是能對這些小塊處理得足夠快,就能達到低延時的效果。
交互式查詢場景,若是數據能全在內存,處理得足夠快的話,就能夠支持交互式查詢。
機器學習和圖計算實際上是和前幾種場景不一樣的 RDD 算子類型。Spark 提供了庫來支持經常使用的操做,用戶或者第三方庫也能夠本身擴展。值得一提的是,Spark 的 RDD 模型和機器學習模型訓練的迭代計算很是契合,從一開始就在有的場景帶來了很是顯著的性能提高。
從這些能夠看出來,比起 Hadoop MapReduce, Spark 本質上就是基於內存的更快的批處理。而後用足夠快的批處理來實現各類場景。
(來源: www.slideshare.net/ParisCarbon…前面說過,在Flink 中,若是輸入數據流是有邊界的,就天然達到了批處理的效果。這樣流和批的區別徹底是邏輯上的,和處理實現獨立,用戶須要實現的邏輯也徹底同樣,應該是更乾淨的一種抽象。後續會在深刻對比流計算方面的時候作更深刻的討論。
Flink 也提供了庫來支持機器學習,圖計算等場景。從這方面來講和 Spark 沒有太大區別。
一個有意思的事情是用 Flink 的底層 API 能夠支持只用 Flink集羣實現一些數據驅動的分佈式服務。有一些公司用 Flink集羣實現了社交網絡,網絡爬蟲等服務。這個也體現了 Flink 做爲計算引擎的通用性,並得益於 Flink 內置的靈活的狀態支持。
總的來講,Spark 和 Flink 都瞄準了在一個執行引擎上同時支持大多數數據處理場景,也應該都能作到這一點。主要區別就在於由於架構自己的侷限在一些場景會受到限制。比較突出的地方就是 Spark Streaming 的 micro batch 執行模式。Spark 社區應該也意識到了這一點,最近在持續執行模式(continuous processing)方面開始發力。 具體狀況會在後面介紹。
Flink 還有一個很是獨特的地方是在引擎中引入了託管狀態(managed state)。要理解託管狀態,首先要從有狀態處理提及。若是處理一個事件(或一條數據)的結果只跟事件自己的內容有關,稱爲無狀態處理;反之結果還和以前處理過的事件有關,稱爲有狀態處理。稍微複雜一點的數據處理,好比說基本的聚合,都是有狀態處理。Flink 很早就認爲沒有好的狀態支持是作很差留處理的,所以引入了 managed state 並提供了 API接口。
Flink 中的狀態支持 (來源: www.slideshare.net/ParisCarbon…通常在流處理的時候會比較關注有狀態處理,可是仔細看的話批處理也是會受到影響的。好比常見的窗口聚合,若是批處理的數據時間段比窗口大,是能夠不考慮狀態的,用戶邏輯常常會忽略這個問題。可是當批處理時間段變得比窗口小的時候,一個批的結果實際上依賴於之前處理過的批。這時,由於批處理引擎通常沒有這個需求不會有很好的內置支持,維護狀態就成爲了用戶須要解決的事情。好比窗口聚合的狀況用戶就要加一箇中間結果表記住尚未完成的窗口的結果。這樣當用戶把批處理時間段變短的時候就會發現邏輯變複雜了。這是早期 Spark Streaming 用戶 常常碰到的問題。直到 Structured Streaming 出來才獲得緩解。
而像 Flink 這樣以流處理爲基本模型的引擎,由於一開始就避不開這個問題,因此引入了 managed state 來提供了一個通用的解決方案。比起用戶實現的特定解決方案,不但用戶開發更簡單,並且能提供更好的性能。最重要的是能更好地保證處理結果的一致性。
簡單來講,就是有一些內秉的數據處理邏輯,在批處理中容易被忽略或簡化處理掉也能獲得可用的結果,而在流處理中問題被暴露出來解決掉了。因此流計算引擎用有限流來處理批在邏輯上比較嚴謹,能天然達到正確性。主要作一些不一樣的實現來優化性能就能夠了。而用更小的批來模擬流須要處理一些之前沒有的問題。當計算引擎尚未通用解決方案的時候就須要用戶本身解決了。相似的問題還有維表的變化(好比用戶信息的更新),批處理數據的邊界和遲到數據等等。
Spark 的初衷之一就是用統一的編程模型來解決用戶的各類需求。在這方面一直很下功夫。最初基於 RDD 的 API 就能夠作各類類型的數據處理。後來爲了簡化用戶開發,逐漸推出了更高層的DataFrame(在 RDD 中加了列變成結構化數據)和 Datasets(在 DataFrame 的列上加了類型),並在Spark 2.0 中作了整合(DataFrame = DataSet[Row])。Spark SQL 的支持也比較早就引入了。在加上各個處理類型API 的不斷改進,好比 Structured Streaming 以及和機器學習深度學習的交互,到了今天Spark 的 API 能夠說是很是好用的,也是 Spark 最強的方面之一。
Spark 2.0 API (來源: databricks.com/blog/2016/0…Flink 的API也有相似的目標和發展路線。Flink 和 Spark 的核心 API 能夠說是能夠基本對應的。今天Spark API 整體上更完備一下,好比說最近一兩年大力投入的和機器學習深度學習的整合方面。Flink 在流處理相關的方面仍是領先一些,好比對 watermark,window,trigger 的各類支持。
Flink API (來源: ci.apache.org/projects/fl…Spark 和 Flink 都是通用的可以支持超大規模數據處理,支持各類處理類型的計算引擎。兩個系統都有不少值得探討的方面在這裏沒有觸及,好比 SQL 的優化,和機器學習的集成等等。這裏主要是試圖從最基本的架構和設計方面來比較一下兩個系統。由於上層的功能在必定程度上是能夠互相借鑑的,有足夠的投入應該都能作好。而基本的設計改變起來會傷筋動骨,更困難一些。
Spark 和 Flink 的不一樣執行模型帶來的最大的區別應該仍是在對流計算的支持上。最開始的 Spark Streaming 對流計算想得過於簡單,對複雜一點的計算用起來會有很多問題。從 Spark 2.0 開始引入的 Structured Streaming 從新整理了流計算的語義,支持按事件時間處理和端到端的一致性。雖然在功能上還有很多限制,比以前已經有了長足的進步。不過 micro batch 執行方式帶來的問題仍是存在,特別在規模上去之後性能問題會比較突出。最近 Spark 受一些應用場景的推進,也開始開發持續執行模式。2.3裏的實驗性發布還只支持簡單的 map 類的操做。 Spark 持續執行模式狀態(來源:www.slideshare.net/databricks/…
從最近 Spark+AI Summit 大會上的介紹來看(下圖),會發展成一個和 Flink 的流處理模式比較類似的執行引擎。不過從下圖來看,主要的功能都還在開發中或者待開發。對未來能作到什麼程度,和 Spark 原來的 batch 執行引擎怎麼結合,咱們拭目以待。
更多資訊請訪問 Apache Flink 中文社區網站