在現在數據爆炸的時代,企業的數據量與日俱增,大數據產品層出不窮。今天給你們分享一款產品—— Apache Flink,目前,已經是 Apache 頂級項目之一。那麼,接下來,筆者爲你們介紹Flink 的相關內容。html
Apache Flink 是一個面向分佈式數據流處理和批量數據處理的開源計算平臺,它可以基於同一個Flink運行時(Flink Runtime),提供支持流處理和批處理兩種類型應用的功能。現有的開源計算方案,會把流處理和批處理做爲兩種不一樣的應用類型,由於他們它們所提供的SLA是徹底不相同的:流處理通常須要支持低延遲、Exactly-once保證,而批處理須要支持高吞吐、高效處理,因此在實現的時候一般是分別給出兩套實現方法,或者經過一個獨立的開源框架來實現其中每一種處理方案。例如,實現批處理的開源方案有MapReduce、Tez、Crunch、Spark,實現流處理的開源方案有Samza、Storm。 Flink在實現流處理和批處理時,與傳統的一些方案徹底不一樣,它從另外一個視角看待流處理和批處理,將兩者統一塊兒來:Flink是徹底支持流處理,也就是說做爲流處理看待時輸入數據流是無界的;批處理被做爲一種特殊的流處理,只是它的輸入數據流被定義爲有界的。基於同一個Flink運行時(Flink Runtime),分別提供了流處理和批處理API,而這兩種API也是實現上層面向流處理、批處理類型應用框架的基礎。算法
Flink 是一款新的大數據處理引擎,目標是統一不一樣來源的數據處理。這個目標看起來和 Spark 和相似。這兩套系統都在嘗試創建一個統一的平臺能夠運行批量,流式,交互式,圖處理,機器學習等應用。因此,Flink 和 Spark 的目標差別並不大,他們最主要的區別在於實現的細節。sql
下面附上 Flink 技術棧的一個總覽,以下圖所示:apache
瞭解 Flink 的做用和優缺點,須要有一個參照物,這裏,筆者以它與 Spark 來對比闡述。從抽象層,內存管理,語言實現,以及 API 和 SQL 等方面來贅述。編程
接觸過 Spark 的同窗,應該比較熟悉,在處理批處理任務,可使用 RDD,而對於流處理,可使用 Streaming,然其世紀仍是 RDD,因此本質上仍是 RDD 抽象而來。可是,在 Flink 中,批處理用 DataSet,對於流處理,有 DataStreams。思想相似,但卻有所不一樣:其一,DataSet 在運行時表現爲 Runtime Plans,而在 Spark 中,RDD 在運行時表現爲 Java Objects。在 Flink 中有 Logical Plan ,這和 Spark 中的 DataFrames 相似。於是,在 Flink 中,如果使用這類 API ,會被優先來優化(即:自動優化迭代)。以下圖所示:緩存
然而,在 Spark 中,RDD 就沒有這塊的相關優化,以下圖所示::安全
另外,DataSet 和 DataStream 是相對獨立的 API,在 Spark 中,全部不一樣的 API,好比 Streaming,DataFrame 都是基於 RDD 抽象的。然而在 Flink 中,DataSet 和 DataStream 是同一個公用引擎之上的兩個獨立的抽象。因此,不能把這二者的行爲合併在一塊兒操做,目前官方正在處理這種問題,詳見[FLINK-2320]session
在以前的版本(1.5之前),Spark 延用 Java 的內存管理來作數據緩存,這樣很容易致使 OOM 或者 GC。以後,Spark 開始轉向另外更加友好和精準的控制內存,即:Tungsten 項目。然而,對於 Flink 來講,從一開始就堅持使用本身控制內存。Flink 除把數據存在本身管理的內存以外,還直接操做二進制數據。在 Spark 1.5以後的版本開始,全部的 DataFrame 操做都是直接做用於 Tungsten 的二進制數據上。數據結構
PS:Tungsten 項目將是 Spark 自誕生以來內核級別的最大改動,以大幅度提高 Spark 應用程序的內存和 CPU 利用率爲目標,旨在最大程度上利用硬件性能。該項目包括了三個方面的改進:app
Spark 使用 Scala 來實現的,它提供了 Java,Python 以及 R 語言的編程接口。而對於 Flink 來講,它是使用 Java 實現的,提供 Scala 編程 API。從編程語言的角度來看,Spark 略顯豐富一些。
Spark 和 Flink 二者都傾向於使用 Scala 來實現對應的業務。對比二者的 WordCount 示例,很相似。以下所示,分別爲 RDD 和 DataSet API 的示例代碼:
// Spark WordCount object WordCount { def main(args: Array[String]) { val env = new SparkContext("local","WordCount") val data = List("hi","spark cluster","hi","spark") 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 object WordCount { def main(args: Array[String]) { val env = ExecutionEnvironment.getExecutionEnvironment val data = List("hello","flink cluster","hello") 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()) } }
對於 Streaming,Spark 把它當作更快的批處理,而 Flink 把批處理當作 Streaming 的特殊例子,差別以下:其一,在實時計算問題上,Flink 提供了基於每一個事件的流式處理機制,因此它能夠被認爲是一個真正意義上的流式計算,相似於 Storm 的計算模型。而對於 Spark 來講,不是基於事件粒度的,而是用小批量來模擬流式,也就是多個事件的集合。因此,Spark 被認爲是一個接近實時的處理系統。雖然,大部分應用實時是能夠接受的,但對於不少應用須要基於事件級別的流式計算。於是,會選擇 Storm 而不是 Spark Streaming,如今,Flink 也許是一個不錯的選擇。
目前,Spark SQL 是其組件中較爲活躍的一部分,它提供了相似於 Hive SQL 來查詢結構化數據,API 依然很成熟。對於 Flink 來講,截至到目前 1.0 版本,只支持 Flink Table API,官方在 Flink 1.1 版本中會添加 SQL 的接口支持。[Flink 1.1 SQL 詳情計劃]
Flink 包含一下特性:
Flink 的流處理引擎只須要不多配置就能實現高吞吐率和低延遲。下圖展現了一個分佈式計數的任務的性能,包括了流數據 shuffle 過程。
Flink 支持了流處理和 Event Time 語義的窗口機制。Event time 使得計算亂序到達的事件或可能延遲到達的事件更加簡單。以下圖所示:
流程序能夠在計算過程當中維護自定義狀態。Flink 的 checkpointing 機制保證了即時在故障發生下也能保障狀態的 exactly once 語義。
Flink 支持在時間窗口,統計窗口,session 窗口,以及數據驅動的窗口,窗口能夠經過靈活的觸發條件來定製,以支持複雜的流計算模式。
數據流應用執行的是不間斷的(常駐)operators。Flink streaming 在運行時有着自然的流控:慢的數據 sink 節點會反壓(backpressure)快的數據源(sources)。
Flink 的容錯機制是基於 Chandy-Lamport distributed snapshots 來實現的。這種機制是很是輕量級的,容許系統擁有高吞吐率的同時還能提供強一致性的保障。
Flink 爲流處理和批處理應用公用一個通用的引擎。批處理應用能夠以一種特殊的流處理應用高效地運行。以下圖所示:
Flink 在 JVM 中實現了本身的內存管理。應用能夠超出主內存的大小限制,而且承受更少的垃圾收集的開銷。
Flink 具備迭代計算的專門支持(好比在機器學習和圖計算中)。增量迭代能夠利用依賴計算來更快地收斂。以下圖所示:
批處理程序會自動地優化一些場景,好比避免一些昂貴的操做(如 shuffles 和 sorts),還有緩存一些中間數據。
DataStream API 支持了數據流上的函數式轉換,可使用自定義的狀態和靈活的窗口。下面示例展現瞭如何以滑動窗口的方式統計文本數據流中單詞出現的次數。
case class Word(word: String, freq: Long) val texts: DataStream[String] = ... val counts = text .flatMap { line => line.split("\\W+") } .map { token => Word(token, 1) } .keyBy("word") .timeWindow(Time.seconds(5), Time.seconds(1)) .sum("freq")
Flink 的 DataSet API 可使你用 Java 或 Scala 寫出漂亮的、類型安全的、可維護的代碼。它支持普遍的數據類型,不只僅是 key/value 對,以及豐富的 operators。下面示例展現了圖計算中 PageRank 算法的一個核心循環。
case class Page(pageId: Long, rank: Double) case class Adjacency(id: Long, neighbors: Array[Long]) val result = initialRanks.iterate(30) { pages => pages.join(adjacency).where("pageId").equalTo("pageId") { (page, adj, out : Collector[Page]) => { out.collect(Page(page.id, 0.15 / numPages)) for (n <- adj.neighbors) { out.collect(Page(n, 0.85*page.rank/adj.neighbors.length)) } } } .groupBy("pageId").sum("rank") }
Flink 棧中提供了不少高級 API 和知足不一樣場景的類庫:機器學習、圖分析、關係式數據處理。當前類庫還在 beta 狀態,而且在大力發展。
Flink 與開源大數據處理生態系統中的許多項目都有集成。Flink 能夠運行在 YARN 上,與 HDFS 協同工做,從 Kafka 中讀取流數據,能夠執行 Hadoop 程序代碼,能夠鏈接多種數據存儲系統。以下圖所示:
以上,即是對 Flink 作一個簡要的剖析認識,至於如何使用 Flink,以及其編譯,安裝,部署,運行等流程,較爲簡單,這裏就很少作贅述了,你們能夠在 Flink 的官網,閱讀其 QuickStart 便可,[訪問地址]。
這篇博客就和你們分享到這裏,若是你們在研究學習的過程中有什麼問題,能夠加羣進行討論或發送郵件給我,我會盡我所能爲您解答,與君共勉!