Flink vs Spark —— 爲Spark開發者介紹Apache Flink

Madhukar

原文

世界需要另外一個大數據處理系統嗎?這是當我第一次聽說Apache Flink的時候產生的問題。在大數據領域,我們不缺乏框架。不過我們確實缺少一個能夠滿足我們不同數據處理需求的集成平臺。Apache Spark似乎是解決這個問題的最好框架。因此我懷疑是否需要另外一個解決相同問題的框架。

出於好奇,在過去幾周我在Flink上花了點時間。起初,我看了看一些標準的例子。 他們看上去和Spark類似。因此,我對它開始的映象就是另外一個模仿Spark功能的框架。然後,隨着花的時間越來越多,我發現Flink蘊含在那些表面上看上去相同的API後面的新穎的想法與Spark有很大不同。我被那些思想所吸引,因此花了更多的時間去理解和探索。

Flink許多關於內存管理,DataSet API思路都可以在Spark裏面找到,它們已經被證明確實是好的想法。所以理解Flink可以幫助我們理解分佈式數據處理的未來發展方向。

在這篇博客裏我試圖把我作爲開發者對Apache Flink所有的第一印象放在一起。這些吐槽/評論存在大的偏頗,因爲我花了過去的兩年在Spark上,但Apache Flink卻僅僅只有兩三週。所以請把下面我說的當做陋見。

什麼是Apache Flink?

Apache Flink是爲統一不同的數據負載而設計的另一個新的大數據處理引擎。它聽起來像Apache Spark?準確的說,Flink試圖解決和Spark一樣的問題。兩者都是致力於構建運行批處理、流、交互、圖處理及機器學習等平臺。因爲他們在功能上沒有太大的區別。但是他們的實現卻有很大的不同。

所以,在下面一節我會比較Spark和Flink的不同的方面。在這兩個框架中一些方法是相同的,一些卻大相徑庭。

Apache Spark vs Apache Flink

摘要

在Spark裏面,我們有RDD抽象和用於流處理的DStream。DStream內部本身也是RDD。所以我們在Spark裏面組織的數據背後都是使用RDD表示。

在Flink中,我們用DataSet抽象批處理,並在流處理應用中使用DataStreams。它們聽起來很像RDD和DStreams,但其實不是。他們的區別在於:

DataSet表示的是運行時的計劃

Spark裏的RDD運行時以Java對象表示。雖然引入了叫“鎢”的項目,情況有了些變化。在Apache Flink中,Dataset表示邏輯計劃,聽起來很熟悉?沒錯,他們很像Spakr中的Dataframes。所以,在Flink中你可以像API一樣作爲一等公民獲得經過優化器優化的Dataframe。但Spark RDD中間是不做優化的。

Flink的Dataset就像Spark執行前優化的Datafream API

Spark 1.6 加入了Dataset API,其最終會替換RDD

Dataset與DataStream是相互獨立的API

Spark中所有不同的抽象如DStream,Dataframe都是基於RDD。但在Flink,Dataset和DataStream是兩個建立在共同引擎上的不同的抽象。雖然他們API相似,但是你們不能把Dataset和DataStream像DStream和RDD一樣合併在一起。雖然Flink朝這個方向做了一些努力,但結果還不明朗。

我們無法把DataSet和DataStreams像RDD和DStreams一樣合併。

內存管理

Spark1.5之前使用Java 堆棧來緩存數據。雖然這易於項目的啓動,但導致了OOM和垃圾收集暫停的問題。Spark1.5之後使用項目“鎢”(tungsten)實現自定義的內存管理。

Flink從第一天起就使用自定義的內存管理。事實上朝這個方向努力也是Spark的願景之一。 Flink不僅以自定的二進制格式存儲數據,而且還直接以二進制的方式操作數據。Spark1.5開始所有的DataFrame都是直接基於項目“鎢”的二級制數據進行操作。

基於JVM做自定義的內存管理會獲得更好的性能,資源利用率也更高。

語言實現

Spark使用Scala寫的,提供了其他語言的API,比如Java,Python及R等。

Flink使用Java實現的,也提供Scala API。

所以語言選擇方面Spark比Flink更多。另外Flink Scala API,內部是由Java實現的。我認爲隨着越來越多的用戶使用Scala API,這種情況會有所改善。我對Spark和Flink Java API瞭解不多,因爲我轉回Scala很久了。

API

Spark和Flink都是模仿Scala集合API。所以表面上看這兩類API非常相似。

// Spark wordcount

object WordCount {

    def main(args: Array[String]) {

        val env = new SparkContext("local","wordCount")

        val data = List("hi","how are you","hi")

        val dataSet = env.parallelize(data)

        val words = dataSet.flatMap(value => value.split("\\s+"))

        val mappedWords = words.map(value => (value,1))

        val sum = mappedWords.reduceByKey(_+_)

        println(sum.collect())

    }

}

// Flink wordcount

objectWordCount{

    def main(args:Array[String]) {

        val env=ExecutionEnvironment.getExecutionEnvironment

        val data=List("hi","how are you","hi")

        val dataSet=env.fromCollection(data)

        val words=dataSet.flatMap(value=>value.split("\\s+"))

        val mappedWords=words.map(value=>(value,1))

        val grouped=mappedWords.groupBy(0)

        val sum=grouped.sum(1)

        println(sum.collect())

    }

}

雖然我不清楚這是巧合還是故意的,相似的API有助於在這些框架間之間切換。集合API好像在不久的將來將成爲處理數據管道的標準API。Scala之父Martin Odersky甚至也承認這個事實。

Apache Spark把流看作是快速的批處理, 而Apache Flink把批處理看作是流處理的一個特例。這兩種方式都很有意思。下面是一些他們的區別或者說含義:

實時 vs 準實時

Apache Flink 提供事件級別的處理,也就是所謂的實時流。和Storm模型很相似。

而Spark使用迷你批處理,但不支持事件級別的粒度,這就是所謂準實時。

    Spark流是更快的批處理, 而Flink將批處理當做流處理實現。

許多應用使用準實時就可以滿足需求,但少數應用還是需要事件級別的實時處理。這些應用通常涉及的都是真正的流(實時流),而不是Spark準實時流。對於他們來說Flink將是非常有吸引力的選擇。

歷史數據和流合併的能力

以更快的批處理來處理流的好處之一就是我們可以爲批處理和流使用相同的抽象。源於底層使用統一的RDD抽象,Spark對批處理和流數據合併有着出色的支持。

Flink方面,批處理和流沒有使用相同的API抽象。所以儘管也有歷史數據和流合併的方法,但沒有Sparkt那麼清晰。

在許多應用程序內部,這種合併能力很重要,在這種情況下,Spark就會取代Flink流處理而表現優異。

靈活的窗口期

由於迷你批處理本質還是批處理,所以到目前爲止Spark流窗口支持還是非常有限的。你僅僅只能基於處理時間爲批處理劃分窗口。

與其他任何系統相比,Flink提供非常靈活的窗口系統。窗口是Flink流API主要關注點之一。它允許基於處理時間,日期,無記錄(?)等定義窗口。這種靈活性使得Flink流API相對Spark API更強大。

我不清楚把這些API加入到Spark的難易程度,所以,到那時爲止,和Spark流相比,Flink擁有超級窗口API。

SQL interface

到目前爲止,最活躍的的Spakr庫之一就是spark-sql。 Spark提供Hive類查詢語言和Dataframe類DSL查詢結構化數據。這是很成熟的API,在batch裏頭被廣泛使用,不久流處理也會廣泛使用。

到目前爲止,Flink Table API僅支持Dataframe類DSL,並且仍是Beta版。有計劃增加SQL接口,但不確定將什麼時候加入框架中。

所以Spark相對Flink有比較好的SQL支持。我認爲作爲後來者,Flink會很快跟進。

Data Source 集成

Spark Data Source API 是Spark框架中最好的API。它把智能數據源如NoSql數據庫,Parquet,ORC最爲Spark的一等公民。另外,它也提供高級操作的能力,如數據源級別的謂詞下推。

Flink仍然嚴重依賴Map/Reduce InputFormat來做數據源集成。雖然這對拉取數據足夠好了,但它無法智能的使用數據源的能力。所以Flink到目前爲止這塊還是比較滯後。

迭代處理

Spark談的最多的特性之一就是進行有效的機器學些。內存級的緩存和其他實現細節使得它是實現機器學習算法真正強大的平臺。

雖然機器學習是一個循環數據流,但Spark使用有向無環圖(DAG)表示。一般來說,沒有分佈式系統鼓勵使用循環數據流,因爲它們會變得難於理解。

但Flink採用了有別於其他方法的方法。支持運行時控制循環依賴圖。因此,它使用相比DAG更有效的方法來表示機器學習算法。

我希望Spark也開始支持循環依賴圖,這將使得機器學習社區極大獲益。

流平臺VS批處理平臺

Spark源於把整個計算表示成作爲文件集合的數據的運動的Map/Reduce時代。這些文件可能以數組的形式位於內存,或者就是硬盤上的物理文件。這有非常好的容錯等屬性。

但是Flink是一種新型系統,它把整個計算表示成數據無任何障礙流動的流處理。這種思想和新的如akka-streams反應式流系統相似。

雖然憑我有限的調查,似乎不足以判斷哪種是大數據系統的未來。使用流來處理一切好像也是最近興起的。所以從這個意義來說,Flink爲我們思考大數據系統方式帶來了一股新風。

成熟度

瞭解了所有區別之後,你產生的一個問題可能就是Flink是和Spark一樣生產環境就緒的嗎?我認爲還沒有完全就緒。有些部分如批處理已經上生產環境了,但其他的部分如流處理,table API仍然在演進。但這不是說就沒有人在生產環境中使用Flink流處理了。有些勇敢者已經在用了。然而作爲大衆化市場工具它需要隨着時間的推移變得成熟和穩定。

結論

目前,Spark相對Flink是一個更成熟更完整的框架。但Flink帶來了許多如爲Table自定義內存管理,提供data set API等新的有趣的思想。Spark社區瞭解到了並正在將其納入囊中。所以從這個意義上來說,Flink在引領整個大數據處理到下一個階段。所以瞭解Flink API和及其內部實現將有助於你在這種的新的流處理範式登錄Spark之前很好的理解它。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章