一. Flink的引入
這幾年大數(shù)據(jù)的飛速發(fā)展,出現(xiàn)了很多熱門(mén)的開(kāi)源社區(qū),其中著名的有 Hadoop、Storm,以及后來(lái)的 Spark,他們都有著各自專(zhuān)注的應(yīng)用場(chǎng)景。Spark 掀開(kāi)了內(nèi)存計(jì)算的先河,也以?xún)?nèi)存為賭注,贏得了內(nèi)存計(jì)算的飛速發(fā)展。Spark 的火熱或多或少的掩蓋了其他分布式計(jì)算的系統(tǒng)身影。就像 Flink,也就在這個(gè)時(shí)候默默的發(fā)展著。
在國(guó)外一些社區(qū),有很多人將大數(shù)據(jù)的計(jì)算引擎分成了 4 代,當(dāng)然,也有很多人不會(huì)認(rèn)同。我們先姑且這么認(rèn)為和討論。
首先第一代的計(jì)算引擎,無(wú)疑就是 Hadoop 承載的 MapReduce。這里大家應(yīng)該都不會(huì)對(duì) MapReduce 陌生,它將計(jì)算分為兩個(gè)階段,分別為 Map 和 Reduce。對(duì)于上層應(yīng)用來(lái)說(shuō),就不得不想方設(shè)法去拆分算法,甚至于不得不在上層應(yīng)用實(shí)現(xiàn)多個(gè) Job 的串聯(lián),以完成一個(gè)完整的算法,例如迭代計(jì)算。
由于這樣的弊端,催生了支持 DAG 框架的產(chǎn)生。因此,支持 DAG 的框架被劃分為第二代計(jì)算引擎。如 Tez 以及更上層的 Oozie。這里我們不去細(xì)究各種 DAG 實(shí)現(xiàn)之間的區(qū)別,不過(guò)對(duì)于當(dāng)時(shí)的 Tez 和 Oozie 來(lái)說(shuō),大多還是批處理的任務(wù)。
接下來(lái)就是以 Spark 為代表的第三代的計(jì)算引擎。第三代計(jì)算引擎的特點(diǎn)主要是 Job 內(nèi)部的 DAG 支持(不跨越 Job),以及強(qiáng)調(diào)的實(shí)時(shí)計(jì)算。在這里,很多人也會(huì)認(rèn)為第三代計(jì)算引擎也能夠很好的運(yùn)行批處理的 Job。
隨著第三代計(jì)算引擎的出現(xiàn),促進(jìn)了上層應(yīng)用快速發(fā)展,例如各種迭代計(jì)算的性能以及對(duì)流計(jì)算和 SQL 等的支持。Flink 的誕生就被歸在了第四代。這應(yīng)該主要表現(xiàn)在 Flink 對(duì)流計(jì)算的支持,以及更一步的實(shí)時(shí)性上面。當(dāng)然 Flink 也可以支持 Batch 的任務(wù),以及 DAG 的運(yùn)算。
二. Flink簡(jiǎn)介
Apache Flink是一個(gè)框架和分布式處理引擎,用于對(duì)無(wú)界和有界數(shù)據(jù)流進(jìn)行有狀態(tài)計(jì)算。Flink設(shè)計(jì)為在所有常見(jiàn)的集群環(huán)境中運(yùn)行,以?xún)?nèi)存速度和任何規(guī)模執(zhí)行計(jì)算。
1.無(wú)界流和有界流
任何類(lèi)型的數(shù)據(jù)都是作為事件流產(chǎn)生的。信用卡交易,傳感器測(cè)量,機(jī)器日志或網(wǎng)站或移動(dòng)應(yīng)用程序上的用戶(hù)交互,所有這些數(shù)據(jù)都作為流生成。
數(shù)據(jù)可以作為無(wú)界或有界流處理。
-
無(wú)界流有一個(gè)開(kāi)始但沒(méi)有定義的結(jié)束。它們不會(huì)在生成時(shí)終止并提供數(shù)據(jù)。必須持續(xù)處理無(wú)界流,即必須在攝取事件后立即處理事件。無(wú)法等待所有輸入數(shù)據(jù)到達(dá),因?yàn)檩斎胧菬o(wú)界的,并且在任何時(shí)間點(diǎn)都不會(huì)完成。處理無(wú)界數(shù)據(jù)通常要求以特定順序(例如事件發(fā)生的順序)攝取事件,以便能夠推斷結(jié)果完整性。
-
有界流具有定義的開(kāi)始和結(jié)束。可以在執(zhí)行任何計(jì)算之前通過(guò)攝取所有數(shù)據(jù)來(lái)處理有界流。處理有界流不需要有序攝取,因?yàn)榭梢允冀K對(duì)有界數(shù)據(jù)集進(jìn)行排序。有界流的處理也稱(chēng)為批處理。

Apache Flink擅長(zhǎng)處理無(wú)界和有界數(shù)據(jù)集。精確控制時(shí)間和狀態(tài)使Flink的運(yùn)行時(shí)能夠在無(wú)界流上運(yùn)行任何類(lèi)型的應(yīng)用程序。有界流由算法和數(shù)據(jù)結(jié)構(gòu)內(nèi)部處理,這些算法和數(shù)據(jù)結(jié)構(gòu)專(zhuān)門(mén)針對(duì)固定大小的數(shù)據(jù)集而設(shè)計(jì),從而產(chǎn)生出色的性能。
2.隨處部署應(yīng)用程序
Apache Flink是一個(gè)分布式系統(tǒng),需要計(jì)算資源才能執(zhí)行應(yīng)用程序。Flink與所有常見(jiàn)的集群資源管理器(如Hadoop YARN,Apache Mesos和Kubernetes)集成,但也可以設(shè)置為作為獨(dú)立集群運(yùn)行。
Flink旨在很好地適用于之前列出的每個(gè)資源管理器。這是通過(guò)特定于資源管理器的部署模式實(shí)現(xiàn)的,這些模式允許Flink以其慣用的方式與每個(gè)資源管理器進(jìn)行交互。
部署Flink應(yīng)用程序時(shí),F(xiàn)link會(huì)根據(jù)應(yīng)用程序配置的并行性自動(dòng)識(shí)別所需資源,并從資源管理器請(qǐng)求它們。如果發(fā)生故障,F(xiàn)link會(huì)通過(guò)請(qǐng)求新資源來(lái)替換發(fā)生故障的容器。提交或控制應(yīng)用程序的所有通信都通過(guò)REST調(diào)用進(jìn)行。這簡(jiǎn)化了Flink在許多環(huán)境中的集成。
3.以任何比例運(yùn)行應(yīng)用程序
Flink旨在以任何規(guī)模運(yùn)行有狀態(tài)流應(yīng)用程序。應(yīng)用程序可以并行化為數(shù)千個(gè)在集群中分布和同時(shí)執(zhí)行的任務(wù)。因此,應(yīng)用程序可以利用幾乎無(wú)限量的CPU,主內(nèi)存,磁盤(pán)和網(wǎng)絡(luò)IO。而且,F(xiàn)link可以輕松維護(hù)非常大的應(yīng)用程序狀態(tài)。其異步和增量檢查點(diǎn)算法確保對(duì)處理延遲的影響最小,同時(shí)保證一次性狀態(tài)一致性。
用戶(hù)報(bào)告了在其生產(chǎn)環(huán)境中運(yùn)行的Flink應(yīng)用程序的可擴(kuò)展性數(shù)字令人印象深刻,例如
- 應(yīng)用程序每天處理數(shù)萬(wàn)億個(gè)事件,
- 應(yīng)用程序維護(hù)多個(gè)TB的狀態(tài),以及
- 應(yīng)用程序在數(shù)千個(gè)內(nèi)核的運(yùn)行。
4.利用內(nèi)存中的性能
有狀態(tài)Flink應(yīng)用程序針對(duì)本地狀態(tài)訪(fǎng)問(wèn)進(jìn)行了優(yōu)化。任務(wù)狀態(tài)始終保留在內(nèi)存中,或者,如果狀態(tài)大小超過(guò)可用內(nèi)存,則保存在訪(fǎng)問(wèn)高效的磁盤(pán)上數(shù)據(jù)結(jié)構(gòu)中。因此,任務(wù)通過(guò)訪(fǎng)問(wèn)本地(通常是內(nèi)存中)狀態(tài)來(lái)執(zhí)行所有計(jì)算,從而產(chǎn)生非常低的處理延遲。Flink通過(guò)定期和異步檢查本地狀態(tài)到持久存儲(chǔ)來(lái)保證在出現(xiàn)故障時(shí)的一次狀態(tài)一致性。

5.Flink的架構(gòu)
Flink 可以支持本地的快速迭代,以及一些環(huán)形的迭代任務(wù)。并且 Flink 可以定制化內(nèi)存管理。在這點(diǎn),如果要對(duì)比 Flink 和 Spark 的話(huà),F(xiàn)link 并沒(méi)有將內(nèi)存完全交給應(yīng)用層。這也是為什么 Spark 相對(duì)于 Flink,更容易出現(xiàn) OOM 的原因(out of memory)。就框架本身與應(yīng)用場(chǎng)景來(lái)說(shuō),F(xiàn)link 更相似與 Storm。如果之前了解過(guò) Storm 或者 Flume 的讀者,可能會(huì)更容易理解 Flink 的架構(gòu)和很多概念。下面讓我們先來(lái)看下 Flink 的架構(gòu)圖。
我們可以了解到 Flink 幾個(gè)最基礎(chǔ)的概念,Client、JobManager 和 TaskManager。Client 用來(lái)提交任務(wù)給 JobManager,JobManager 分發(fā)任務(wù)給 TaskManager 去執(zhí)行,然后 TaskManager 會(huì)心跳的匯報(bào)任務(wù)狀態(tài)??吹竭@里,有的人應(yīng)該已經(jīng)有種回到 Hadoop 一代的錯(cuò)覺(jué)。確實(shí),從架構(gòu)圖去看,JobManager 很像當(dāng)年的 JobTracker,TaskManager 也很像當(dāng)年的 TaskTracker。然而有一個(gè)最重要的區(qū)別就是 TaskManager 之間是是流(Stream)。其次,Hadoop 一代中,只有 Map 和 Reduce 之間的 Shuffle,而對(duì) Flink 而言,可能是很多級(jí),并且在 TaskManager 內(nèi)部和 TaskManager 之間都會(huì)有數(shù)據(jù)傳遞,而不像 Hadoop,是固定的 Map 到 Reduce。
三. Flink技術(shù)特點(diǎn)
1. 流處理特性
- 支持高吞吐、低延遲、高性能的流處理
- 支持帶有事件時(shí)間的窗口(Window)操作
- 支持有狀態(tài)計(jì)算的Exactly-once語(yǔ)義
- 支持高度靈活的窗口(Window)操作,支持基于time、count、session,以及data-driven的窗口操作
- 支持具有Backpressure功能的持續(xù)流模型
- 支持基于輕量級(jí)分布式快照(Snapshot)實(shí)現(xiàn)的容錯(cuò)
- 一個(gè)運(yùn)行時(shí)同時(shí)支持Batch on Streaming處理和Streaming處理
- Flink在JVM內(nèi)部實(shí)現(xiàn)了自己的內(nèi)存管理
- 支持迭代計(jì)算
- 支持程序自動(dòng)優(yōu)化:避免特定情況下Shuffle、排序等昂貴操作,中間結(jié)果有必要進(jìn)行緩存
2. API支持
- 對(duì)Streaming數(shù)據(jù)類(lèi)應(yīng)用,提供DataStream API
- 對(duì)批處理類(lèi)應(yīng)用,提供DataSet API(支持Java/Scala)
3. Libraries支持
- 支持機(jī)器學(xué)習(xí)(FlinkML)
- 支持圖分析(Gelly)
- 支持關(guān)系數(shù)據(jù)處理(Table)
- 支持復(fù)雜事件處理(CEP)
4. 整合支持
- 支持Flink on YARN
- 支持HDFS
- 支持來(lái)自Kafka的輸入數(shù)據(jù)
- 支持Apache HBase
- 支持Hadoop程序
- 支持Tachyon
- 支持ElasticSearch
- 支持RabbitMQ
- 支持Apache Storm
- 支持S3
- 支持XtreemFS
5. Flink生態(tài)圈
Flink 首先支持了 Scala 和 Java 的 API,Python 也正在測(cè)試中。Flink 通過(guò) Gelly 支持了圖操作,還有機(jī)器學(xué)習(xí)的 FlinkML。Table 是一種接口化的 SQL 支持,也就是 API 支持,而不是文本化的 SQL 解析和執(zhí)行。對(duì)于完整的 Stack 我們可以參考下圖。
Flink 為了更廣泛的支持大數(shù)據(jù)的生態(tài)圈,其下也實(shí)現(xiàn)了很多 Connector 的子項(xiàng)目。最熟悉的,當(dāng)然就是與 Hadoop HDFS 集成。其次,F(xiàn)link 也宣布支持了 Tachyon、S3 以及 MapRFS。不過(guò)對(duì)于 Tachyon 以及 S3 的支持,都是通過(guò) Hadoop HDFS 這層包裝實(shí)現(xiàn)的,也就是說(shuō)要使用 Tachyon 和 S3,就必須有 Hadoop,而且要更改 Hadoop 的配置(core-site.xml)。如果瀏覽 Flink 的代碼目錄,我們就會(huì)看到更多 Connector 項(xiàng)目,例如 Flume 和 Kafka。
四. Flink的編程模型
Flink提供不同級(jí)別的抽象來(lái)開(kāi)發(fā)流/批處理應(yīng)用程序。