Flink:下一代StreamCompute平台?

來源:互聯網
上載者:User
簡介

Flink是一個基於StreamCompute的分布式引擎,以前的名字叫stratosphere,從2010年開始在德國一所大學裡發起,也是有好幾年的曆史了,2014年來借鑒了社區其它一些項目的理念,快速發展並且進入了Apache頂級孵化器。

Spark以批次計算的底層引擎同時支援批次計算和StreamCompute(把流切成小批),不同的是,Flink以StreamCompute的底層引擎同時支援批次計算和StreamCompute,Flink提供了DataSet和DataStream的API,並在其上提供機器學習和圖計算的庫。最近,Flink也在發展SQL相關的API(Table),類似Spark中的DataFrame。

(此文預設讀者有一定StreamCompute基礎,Storm經驗)


優勢 1.高吞吐且低延時
在簡單case中,Flink吞吐可以是Storm的10倍,而延時在毫秒級(100ms以內)。 Storm以record by record的常駐任務模式,提供即時的計算,延時可在幾十毫秒甚至10毫秒以內,但帶來的代價是比較低的吞吐。Trident把資料流劃成批次,但是執行起來仍然是Record層級的。所以Storm中,提高吞吐的有效方法是打包。 Spark Streaming不同於常駐任務模式,它將資料直接劃成離散流,這樣將StreamCompute轉換成了批次計算,每一批都進行一次調度來運行,提高了吞吐,但是延時卻依賴固定劃成的時間段,時間段不能設定過小,因為每一批都會有任務調度等等的開銷,一般Spark官方建議2-5s的時間段劃分。
Flink同樣提供了常駐任務的模式,並且為了克服RecordByRecord中輸送量的問題,Flink發送資料時按照記憶體片來發送。記憶體片預設32KB,Flink把將要發送的資料序列化到記憶體片中,當記憶體片湊滿或者逾時,將此記憶體片發送出去,這裡其實就有一個打包的邏輯,但是Flink不同於Storm的使用者簡單打包,Flink將資料直接序列化到受管理的記憶體byte數組中,這樣這些業務對象很快被YoungGC掉了,不會導致FullGC頻繁。 另外一方面,Flink的高吞吐也得益於它的序列化方式,通過DataStreamAPI,Flink瞭解到業務資料的Schema,從而產生定製化的序列化器,避免了昂貴的Kryo序列化(類型資訊,各種反射)。 問題:打包即帶來了一定延時(當資料量不大時會等逾時Flush,當然可以將逾時設定為0,這樣每次寫入都會把資料Flush),達到當拓撲很深時,延時會線性加大。但是Flink會把沒有shuffle(Storm中的FieldGroup)的多個Transform組合最佳化到一起,所以以前在Storm上很多級的拓撲會在Flink中精簡很多,拓撲不會很深。 (Storm 1.0 也做了打包相關的工作,但是思路並不是點到點的打包,而是DisruptorQueue的打包,效能能有3-10倍的提升)
2.Exactly-Once計算和狀態管理 一般的ExactlyOnce語義要求狀態的事務性,受Chandy-Lamport演算法啟發,Flink解決Exactly-Once的思路是定時進行一個一致性分布式snapshot的checkpoint,然後在出錯後,恢複到上一個一致性的snapshot中,這與Trident的基本思路都是一致的,但是具體的實現卻有一定區別。 Trident的事務分為兩階段: 1.並行的計算:這個階段是單純的計算,不牽涉對狀態的改變,批之間沒有關係。 2.狀態的commit:將狀態落地到外部儲存中,這個階段完全是串列的,所以外部引擎單純的增量KV更新就可,不用多版本等概念(這裡只討論Transaction語義,不包括Opaque)。 Trident中是由Master控制整個計算,Master通知source發資料,才進行一批的計算,而Master並不知道當前是否有資料,這就導致了空批問題,當沒有資料時,各種協調訊息大量發送。對此,Trident添加了一個參數,限制批與批之間的最小間隔,但是這就直接導致資料延時取決於這個參數的設定(類似Spark Streaming)。

Flink事務: 與Trident不同,Flink的Master不控制什麼時候發資料,它只控制什麼時候劃分批。 Master會發送Barrier控制流程,將Source的資料分為一批批,而Source可以隨時發送資料。
Master使用Barrier命令控制各個節點,從而產生一個個分布式快照(全量產生、多版本),Master會按一定策略清理無用版本(最新的savepoint甚至可以讓使用者向git一樣管理這些分布式snapshot的版本)。 Barrier的傳播類似Trident中的協調訊息的傳播,假如上遊n個並發、下遊m個並發,共需要n*m的訊息量進行傳播。具體過程參考下圖:
但是這就造成一個問題:假如一個節點有並發A和並發B,它的下遊節點有並發C。 1.當A處理完第1批把Barrier1發送給C,這時B還沒處理第一批。 2.A已經處理完第2批把Barrier2發送給C,這時B還沒處理第一批。 3.這時C已經拿到A發來的第一批和第二批的資料,這時它並不能處理第二批的資料,因為第一批的資料還不全,還不能構成一個分布式的一致性Snapshot,所以它需要把A發來的資料根據Barrier2來阻塞住。 所以關鍵還是分布式一致性要求資料的對齊。而Flink依靠Barrier這種機制來進行分布式一致性的對齊。
如圖描述了節點的4個狀態: 1.開始對齊,這時已經收到A的資料,但是B的資料還沒來,需要對齊。 2.收到上遊A來的下一批的資料,需要把這些資料阻塞住(也就是緩衝起來)。 3.收完B發來的這批的資料,開始進行checkpoint,並發送Barrier到它的下遊去。 4.繼續下一批的對齊。 Barrier的發送完全是按照時間間隔來的,並且完全不影響資料的時延,使用者可以根據恢復的需求來設定間隔。 Flink在checkpoint時會把state複製一份,然後進行非同步checkpoint,盡量不影響正常的計算。
問題1:異常後會導致Flink把整個作業ReDeploy(因為Barrier的存在不易設計rollback),但是Flink是執行緒模式,ReDeploy時並不會銷毀進程,所以代價很低(類似SparkStreaming每批次計算都會Deploy一次)。 問題2:狀態不夠靈活,強要求Key是shuffle中的那個key,這點上可以靠Hack代碼來解決。 問題3:目前狀態的checkpoint還是全量的,還不支援增量checkpoint。
3.逐級反壓 StreamCompute中資料的來源是不穩定的,有可能會突然出現大量的資料,這時會把整個拓撲給壓掛(記憶體OOM等)。 所以StreamCompute中需要有流控的手段,Storm中使用Spout MaxPending來進行流控。 問題是使用者不容易設定這個值,設定小了,整個作業輸送量上不去(沒有達到完全流水線計算),設定大了,容易導致掛掉,從而被卡死。 Twitter在2014年的Storm論文中描述了一種auto-tuning的maxPending設定的機制,根據當前視窗ack回來的資料量對spout的maxPending參數進行動態調整。 而2015年Twitter提出Heron比較好的解決這一問題:使用反壓,當下遊節點撐不住時反壓上遊節點,從而讓Source(spout)發送資料減少。 但是Heron和Storm一樣,底層都是共用串連的方式,如果直接使用TCP反壓,會導致分布式死結的問題,所以它們都只實現了Spout反壓(直接通知Spout)。
Flink的Task和Task之間獨立一條TCP串連,這樣Flink可以直接依靠TCP的反壓。 壞處是底層串連數大量增加。 好處是能減少震蕩問題,Spout反壓中,當下遊發生了擁塞,直接通知Spout,Spout停止發送資料。但是Spout的減小資料量會很久才能反應到下遊,會有很久才能緩解,當停止反壓後,Spout又發送一大批資料,又導致下遊擁塞。這樣的現象是節點在擁塞-空閑狀態來回切換,嚴重影響吞吐。如果能直接反壓上遊,這樣的震蕩影響將會小很多(進一步精細的控制將會繼續減小震蕩)。
問題:依靠TCP來反壓要求Task點到點建立單條串連,這樣當並發較高時,串連數N*M的規模會太大,在這點上,Flink依靠較高的吞吐,可以讓作業的並發設定不那麼大。

4.基於YARN和執行緒模式 基於YARN就意味著可以進行資源的隔離,而且更易部署和管理,能和上面的儲存引擎(Hadoop/HBase等)進行本地互動等等。 Flink運行作業分為兩步: 1.建立AppMaster,申請資源並啟動進程。 2.提交作業。 所以Flink運行作業的方式是執行緒模式,進程預先啟動好,使用者提交作業後,分配到各個進程上運行。這樣設計的好處主要有兩個: 1.大大加快了作業運行速度,作業如果分發好Jar包,啟動速度是毫秒層級的。 2.作業之間可以通過JVM來共用一些資料,Flink最開始的想法就是讓Batch和Stream共用一份資料(甚至包括查詢)。 問題:執行緒模式使得各個Job共用JVM,也會導致它們相互幹擾,在這點上,Flink把選擇權交給了使用者,使用者可以選擇公用一個FlinkApp,也可另起App。
5.靈活視窗計算 Flink中可以使用三種時間來進行視窗的運算: 1.EventTime:事件中內建時間欄位。 2.ProcessingTime:進行視窗計算時的系統時間。 3.IngestionTime:事件進行Flink的時間(Source拿到資料的時間),可以認為是EventTime的一種。
在觸發計算和LateEvent的處理中,Flink使用了Watermark的機制(WheelMill/Dataflow的概念)。 由於分布式環境中各個節點各個資料的時間都不確定,需要有一個統計的訊息來確定時間,這就是Watermark的含義,它用來劃分視窗的邊界。 節點拿到watermark後,就可以根據此時間結束視窗的攢資料,計算輸出並清除這個視窗,過後的lateEvent可以直接扔了或update曆史值(具體邏輯都由使用者定義)。 在實現方面,每個Source單獨產生自己的watermark,下遊節點收到watermark後,根據所有上遊發來的watermark,使用最小的來當做自己的時間,並廣播到下遊。
(有點類似Barrier的感覺)
Flink的視窗很靈活,使用者可以實現自己的視窗定義,也可直接使用TumblingWindow、SlidingWindow、SessionWindow。可以根據資料/內部定時器/watermark來定義觸發輸出的Trigger、觸發清理資料的Trigger。 在視窗上,可以進行多個流的Join操作。 Flink會使用上文的stateCheckpoint機制來對視窗的資料進行容錯處理。
Flink還在不斷完善中,從模型上來說是要比Storm先進一些,進一步可參考官方文檔及源碼。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.