第 1 章 為何選擇 Flink
- 許多情況下灸叼,人們希望用低延遲或者實時的流處理來獲得數(shù)據(jù)的高時效性,前提是流處理本身是準(zhǔn)確且高效的
- 優(yōu)秀的流處理技術(shù)可以容錯寂屏,而且能保證
exactlyonce
2 -
Storm
提供了低延遲的流處理定庵,但是它為實時性付出了一些代價:很難實現(xiàn)高吞吐记餐,并且其正確性沒能達到通常所需的水平督禽。換句話說凌摄,它并不能保證exactlyonce
浪秘;即便是它能夠保證的正確性級別需频,其開銷也相當(dāng)大
圖12:
Flink
的一個優(yōu)勢是丁眼,它擁有諸多重要的流式計算功能。其他項目為了實現(xiàn)這些功能昭殉,都不得不付出代價苞七。比如,Storm
實現(xiàn)了低延遲挪丢,但是在作者撰寫本書時還做不到高吞吐蹂风,也不能在故障發(fā)生時準(zhǔn)確地處理計算狀態(tài);SparkStreaming
通過采用微批處理方法實現(xiàn)了高吞吐和容錯性乾蓬,但是犧牲了低延遲和實時處理能力惠啄,也不能使窗口與自然時間相匹配,并且表現(xiàn)力欠佳
- “
ApacheFlink
是為分布式任内、高性能撵渡、隨時可用以及準(zhǔn)確的流處理應(yīng)用程序打造的開源流處理框架∷类拢”Flink
不僅能提供同時支持高吞吐和exactlyonce
語義的實時計算趋距,還能提供批量數(shù)據(jù)處理 -
flink
一詞表示快速和靈巧。項目采用一只松鼠的彩色圖案作為logo
越走,這不僅因為松鼠具有快速和靈巧的特點棚品,還因為柏林的松鼠有一種迷人的紅棕色 - 2014年12月一躍成為
Apache
軟件基金會的頂級項目靠欢。作為Apache
軟件基金會的5個最大的大數(shù)據(jù)項目之一廊敌,Flink
在全球范圍內(nèi)擁有200多位開發(fā)人員,以及若干公司中的諸多上線場景门怪,有些甚至是世界500強的公司 -
Flink
是如何同時實現(xiàn)批處理與流處理的呢骡澈?答案是,Flink
將批處理(即處理有限的靜態(tài)數(shù)據(jù))視作一種特殊的流處理 -
FlinkRuntime
執(zhí)行引擎可以作為YARN
(YetAnotherResourceNegotiator
)的應(yīng)用程序在集群上運行掷空,也可以在Mesos
集群上運行肋殴,還可以在單機上運行(這對于調(diào)試Flink
應(yīng)用程序來說非常有用)
圖14:
Flink
技術(shù)棧的核心組成部分。值得一提的是坦弟,Flink
分別提供了面向流處理的接口(DataStreamAPI
)和面向批處理的接口(DataSetAPI
)护锤。因此,Flink
既可以完成流處理酿傍,也可以完成批處理烙懦。Flink
支持的拓展庫涉及機器學(xué)習(xí)(FlinkML
)、復(fù)雜事件處理(CEP
)赤炒,以及圖計算(Gelly
)氯析,還有分別針對流處理和批處理的TableAPI
-
Flink
解決了許多問題亏较,比如保證了exactlyonce
語義和基于事件時間的數(shù)據(jù)窗口。開發(fā)人員不再需要在應(yīng)用層解決相關(guān)問題掩缓,這大大地降低了出現(xiàn)bug
的概率 - 不用再在編寫應(yīng)用程序代碼時考慮如何解決問題雪情,所以工程師的時間得以充分利用,整個團隊也因此受益你辣。好處并不局限于縮短開發(fā)時間巡通,隨著靈活性的增加,團隊整體的開發(fā)質(zhì)量得到了提高绢记,運維工作也變得更容易扁达、更高效
布衣格電信
支持真正的流處理——通過上層的
API
和下層的執(zhí)行引擎都能實時進行流處理,這滿足了我們對可編程性和低延遲的需求蠢熄。此外跪解,使用Flink
,我們的系統(tǒng)得以快速上線签孔,這是其他任何一種方案都做不到的叉讥。如此一來,我們就有了更多的人手開發(fā)新的業(yè)務(wù)邏輯
-
ETL
是Extract
饥追、Transform
和Load
的縮寫图仓,即抽取、轉(zhuǎn)換和加載
第 2 章 流處理架構(gòu)
- 以流為基礎(chǔ)的架構(gòu)設(shè)計讓數(shù)據(jù)記錄持續(xù)地從數(shù)據(jù)源流向應(yīng)用程序但绕,并在各個應(yīng)用程序間持續(xù)流動救崔。沒有一個數(shù)據(jù)庫來集中存儲全局狀態(tài)數(shù)據(jù),取而代之的是共享且永不停止的流數(shù)據(jù)捏顺,它是唯一正確的數(shù)據(jù)源六孵,記錄了業(yè)務(wù)數(shù)據(jù)的歷史。在流處理架構(gòu)中幅骄,每個應(yīng)用程序都有自己的數(shù)據(jù)劫窒,這些數(shù)據(jù)采用本地數(shù)據(jù)庫或分布式文件進行存儲
消息傳輸層和流處理層
- 如何有效地實現(xiàn)流處理架構(gòu)并從
Flink
中獲益呢?一個常見的做法是設(shè)置消息傳輸層和流處理層 - (1)消息傳輸層從各種數(shù)據(jù)源(生產(chǎn)者)采集連續(xù)事件產(chǎn)生的數(shù)據(jù)拆座,并傳輸給訂閱了這些數(shù)據(jù)的應(yīng)用程序和服務(wù)(消費者)
- (2)流處理層有3個用途:
- 持續(xù)地將數(shù)據(jù)在應(yīng)用程序和系統(tǒng)間移動主巍;
- 聚合并處理事件;
- 在本地維持應(yīng)用程序的狀態(tài)
圖21:
Flink
項目的架構(gòu)有兩個主要組成部分:消息傳輸層和由Flink
提供的流處理層挪凑。消息傳輸層負(fù)責(zé)傳輸連續(xù)事件產(chǎn)生的消息孕索,能夠提供消息傳輸?shù)南到y(tǒng)包括Kafka
和MapRStreams
。MapRStreams
是MapR
融合數(shù)據(jù)平臺的一個主要組成部分躏碳,它兼容KafkaAPI
- 兼具高性能和持久性對于消息傳輸系統(tǒng)來說至關(guān)重要搞旭;
Kafka
和MapRStreams
都可以滿足這個需求 - 具有持久性的好處之一是消息可以重播
第 3 章 Flink 的用途
-
Flink
解決了可能影響正確性的幾個問題,包括如何在故障發(fā)生之后仍能進行有狀態(tài)的計算 -
Flink
所用的技術(shù)叫作檢查點(checkpoint
) - 在每個檢查點,系統(tǒng)都會記錄中間計算狀態(tài)选脊,從而在故障發(fā)生時準(zhǔn)確地重置杭抠。這一方法使系統(tǒng)以低開銷的方式擁有了容錯能力——當(dāng)一切正常時,檢查點機制對系統(tǒng)的影響非常小
-
Flink
還承擔(dān)了跟蹤計算狀態(tài)的任務(wù)恳啥,從而減輕了開發(fā)人員的負(fù)擔(dān)偏灿,簡化了編程工作,并提高了應(yīng)用程序的成功率钝的。用同一種技術(shù)來實現(xiàn)流處理和批處理翁垂,大大地簡化了開發(fā)和運維工作
第 4 章 對時間的處理
- 用流處理器編程和用批處理器編程最關(guān)鍵的區(qū)別在于對時間的處理。舉一個非常簡單的例子:計數(shù)硝桩。事件流數(shù)據(jù)(如微博內(nèi)容沿猜、點擊數(shù)據(jù)和交易數(shù)據(jù))不斷產(chǎn)生,我們需要用
key
將事件分組碗脊,并且每隔一段時間(比如一小時)就針對每一個key
對應(yīng)的事件計數(shù)啼肩。這是眾所周知的“大數(shù)據(jù)”應(yīng)用,與MapReduce
的詞頻統(tǒng)計例子相似 - 流處理區(qū)別于批處理最主要的兩點是:
- 流即是流衙伶,不必人為地將它分割為文件祈坠;
- 時間的定義被明確地寫入應(yīng)用程序代碼(如以上代碼的時間窗口),而不是與攝取矢劲、計算和調(diào)度等過程牽扯不清
- 流處理系統(tǒng)中的批處理必須符合以下兩點要求
- 批處理只作為提高系統(tǒng)性能的機制赦拘。批量越大,系統(tǒng)的吞吐量就越大
- 為了提高性能而使用的批處理必須完全獨立于定義窗口時所用的緩沖芬沉,或者為了保證容錯性而提交的代碼躺同,也不能作為
API
的一部分。否則丸逸,系統(tǒng)將受到限制蹋艺,并且變得脆弱且難以使用
- 在流處理中,主要有兩個時間概念
- 事件時間椭员,即事件實際發(fā)生的時間车海。更準(zhǔn)確地說笛园,每一個事件都有一個與它相關(guān)的時間戳隘击,并且時間戳是數(shù)據(jù)記錄的一部分(比如手機或者服務(wù)器的記錄)。事件時間其實就是時間戳
- 處理時間研铆,即事件被處理的時間埋同。處理時間其實就是處理事件的機器所測量的時間
圖4-4:事件時間順序與處理時間順序不一致的亂序事件流
- 窗口是一種機制,它用于將許多事件按照時間或者其他特征分組棵红,從而將每一組作為整體進行分析(比如求和)
- 時間窗口是最簡單和最有用的一種窗口凶赁。它支持滾動和滑動。舉一個例子,假設(shè)要對傳感器輸出的數(shù)值求和
圖45:一分鐘滾動窗口計算最近一分鐘的數(shù)值總和
圖46:一分鐘滑動窗口每半分鐘計算一次最近一分鐘的數(shù)值總和
- 在
Flink
中虱肄,一分鐘滾動窗口的定義如下 -
Flink
支持的另一種常見窗口叫作計數(shù)窗口致板。采用計數(shù)窗口時,分組依據(jù)不再是時間戳咏窿,而是元素的數(shù)量斟或。例如,圖46中的滑動窗口也可以解釋為由4個元素組成的計數(shù)窗口集嵌,并且每兩個元素滑動一次萝挤。滾動和滑動的計數(shù)窗口分別定義如下 - 雖然計數(shù)窗口有用,但是其定義不如時間窗口嚴(yán)謹(jǐn)根欧,因此要謹(jǐn)慎使用
- 一種解決辦法是用時間窗口來觸發(fā)超時
-
Flink
支持的另一種很有用的窗口是會話窗口
- 會話指的是活動階段怜珍,其前后都是非活動階段,例如用戶與網(wǎng)站進行一系列交互(活動階段)之后凤粗,關(guān)閉瀏覽器或者不再交互(非活動階段)酥泛。會話需要有自己的處理機制,因為它們通常沒有固定的持續(xù)時間(有些30秒就結(jié)束了嫌拣,有些則長達一小時)揭璃,或者沒有固定的交互次數(shù)(有些可能是3次點擊后購買,另一些可能是40次點擊卻沒有購買)
- 每一個默認(rèn)窗口都有一個觸發(fā)器亭罪。例如瘦馍,采用事件時間的時間窗口將在收到水印時被觸發(fā)。對于用戶來說应役,除了收到水印時生成完整情组、準(zhǔn)確的結(jié)果之外,也可以實現(xiàn)自定義的觸發(fā)器(例如每秒提供一次近似結(jié)果)
- 在
Flink
內(nèi)部箩祥,所有類型的窗口都由同一種機制實現(xiàn) - 開窗機制與檢查點機制(第5章將詳細討論)完全分離院崇。這意味著窗口時長不依賴于檢查點間隔。事實上袍祖,窗口完全可以沒有“時長”(比如上文中的計數(shù)窗口和會話窗口的例子)
- 高級用戶可以直接用基本的開窗機制定義更復(fù)雜的窗口形式(如某種時間窗口底瓣,它可以基于計數(shù)結(jié)果或某一條記錄的值生成中間結(jié)果)
- 時空穿梭意味著將數(shù)據(jù)流倒回至過去的某個時間,重新啟動處理程序蕉陋,直到處理至當(dāng)前時間為止捐凭。像
Kafka
和MapRStreams
這樣的現(xiàn)代傳輸層,支持時空穿梭凳鬓,這使得它們與更早的解決方案有所區(qū)別 -
Flink
通過水印來推進事件時間茁肠。水印是嵌在流中的常規(guī)記錄,計算程序通過水印獲知某個時間點已到 - 在
Flink
中缩举,水印由應(yīng)用程序開發(fā)人員生成垦梆,這通常需要對相應(yīng)的領(lǐng)域有一定的了解匹颤。完美的水印永遠不會錯:時間戳小于水印標(biāo)記時間的事件不會再出現(xiàn) - 設(shè)定水印通常需要用到領(lǐng)域知識。舉例來說托猩,如果知道事件的遲到時間不會超過5秒印蓖,就可以將水印標(biāo)記時間設(shè)為收到的最大時間戳減去5秒。另一種做法是京腥,采用一個
Flink
作業(yè)監(jiān)控事件流另伍,學(xué)習(xí)事件的遲到規(guī)律,并以此構(gòu)建水印生成模型 - 該架構(gòu)在不斷地適應(yīng)(學(xué)習(xí))新系統(tǒng)常態(tài)的同時绞旅,能夠快速且準(zhǔn)確地發(fā)現(xiàn)異常摆尝。這使它成為理想工具,并能夠極大地降低因大型計算設(shè)施運行而產(chǎn)生的維護成本
圖48展示了愛立信團隊構(gòu)建的數(shù)據(jù)管道
- 推送給
Kafka
的原始數(shù)據(jù)是來自云基礎(chǔ)設(shè)施中的所有實體機和虛擬機的遙測信息和日志事件因悲。它們經(jīng)過不同的Flink
作業(yè)消費之后堕汞,被寫回Kafka
主題里,然后再從Kafka
主題里被推送給搜索引擎Elasticsearch
和可視化系統(tǒng)Kibana
晃琳。這種架構(gòu)讓每個Flink
作業(yè)所執(zhí)行的任務(wù)有清晰的定義讯检,一個作業(yè)的輸出可以成為另一個作業(yè)的輸入
第 5 章 有狀態(tài)的計算
- 流式計算分為無狀態(tài)和有狀態(tài)兩種情況。無狀態(tài)的計算觀察每個獨立事件卫旱,并根據(jù)最后一個事件輸出結(jié)果
- 有狀態(tài)的計算則會基于多個事件輸出結(jié)果
- 第4章討論的所有類型的窗口人灼。例如,計算過去一小時的平均溫度顾翼,就是有狀態(tài)的計算
- 所有用于復(fù)雜事件處理的狀態(tài)機投放。例如,若在一分鐘內(nèi)收到兩個相差20度以上的溫度讀數(shù)适贸,則發(fā)出警告灸芳,這是有狀態(tài)的計算
- 流與流之間的所有關(guān)聯(lián)操作,以及流與靜態(tài)表或動態(tài)表之間的關(guān)聯(lián)操作拜姿,都是有狀態(tài)的計算
- 無狀態(tài)流處理分別接收每條記錄(圖中的黑條)烙样,然后根據(jù)最新輸入的記錄生成輸出記錄(白條)
- 有狀態(tài)流處理會維護狀態(tài)(根據(jù)每條輸入記錄進行更新),并基于最新輸入的記錄和當(dāng)前的狀態(tài)值生成輸出記錄(灰條)
圖5-1:無狀態(tài)流處理與有狀態(tài)流處理的區(qū)別蕊肥。輸入記錄由黑條表示谒获。無狀態(tài)流處理每次只轉(zhuǎn)換一條輸入記錄,并且僅根據(jù)最新的輸入記錄輸出結(jié)果(白條)壁却。有狀態(tài)流處理維護所有已處理記錄的狀態(tài)值批狱,并根據(jù)每條新輸入的記錄更新狀態(tài),因此輸出記錄(灰條)反映的是綜合考慮多個事件之后的結(jié)果
- 在流處理中儒洛,一致性分為3個級別
-
atmostonce
:這其實是沒有正確性保障的委婉說法——故障發(fā)生之后精耐,計數(shù)結(jié)果可能丟失 -
atleastonce
:這表示計數(shù)結(jié)果可能大于正確值狼速,但絕不會小于正確值琅锻。也就是說,計數(shù)程序在發(fā)生故障后可能多算,但是絕不會少算 -
exactlyonce
:這指的是系統(tǒng)保證在發(fā)生故障后得到的計數(shù)結(jié)果與正確值一致
-
Flink
的一個重大價值在于恼蓬,它既保證了exactlyonce
惊完,也具有低延遲和高吞吐的處理能力
圖5-2:數(shù)環(huán)狀項鏈上的珠子看上去毫無意義(甚至有些徒勞無功,因為可以永不停歇地計數(shù))处硬,但是它可以用來很好地類比處理永不結(jié)束的事件流小槐。在某些文化中,人們?nèi)耘f將數(shù)珠子視作消磨時間的好方法
- 在項鏈上每隔一段就松松地系上一根有色皮筋荷辕,將珠子分隔開凿跳;當(dāng)珠子被撥動的時候,皮筋也可以被撥動疮方;然后控嗜,你安排一個助手,讓他在你和朋友撥到皮筋時記錄總數(shù)骡显。用這種方法疆栏,當(dāng)有人數(shù)錯時,就不必從頭開始數(shù)惫谤。相反壁顶,你向其他人發(fā)出錯誤警示,然后你們都從上一根皮筋處開始重數(shù)溜歪,助手則會告訴每個人重數(shù)時的起始數(shù)值若专,例如在粉色皮筋處的數(shù)值是多少
- 按照輸入記錄的第一個字段(一個字符串)進行分組并維護第二個字段的計數(shù)狀態(tài)
- 該程序有兩個算子:
keyBy
算子用來將記錄按照第一個元素(一個字符串)進行分組,根據(jù)該key
將數(shù)據(jù)進行重新分區(qū)蝴猪,然后將記錄再發(fā)送給下一個算子:有狀態(tài)的map
算子(mapWithState
)富岳。map
算子在接收到每個元素后,將輸入記錄的第二個字段的數(shù)據(jù)加到現(xiàn)有總數(shù)中拯腮,再將更新過的元素發(fā)射出去
圖5-3:程序的初始狀態(tài)窖式。注意,
a
动壤、b
萝喘、c
三組的初始計數(shù)狀態(tài)都是0,即三個圓柱上的值琼懊。ckpt
表示檢查點屏障阁簸。每條記錄在處理順序上嚴(yán)格地遵守在檢查點之前或之后的規(guī)定,例如["b
",2]在檢查點之前被處理哼丈,["a
",2]則在檢查點之后被處理
圖5-4:當(dāng)
Flink
數(shù)據(jù)源(在本例中與keyBy
算子內(nèi)聯(lián))遇到檢查點屏障時启妹,它會將其在輸入流中的位置保存到穩(wěn)定存儲中。這讓Flink
可以根據(jù)該位置重啟輸入
圖5-6:檢查點操作完成醉旦,狀態(tài)和位置均已備份到穩(wěn)定存儲中饶米。輸入流中的所有記錄都已處理完成桨啃。值得注意的是,備份的狀態(tài)值與實際的狀態(tài)值是不同的檬输。備份反映的是檢查點的狀態(tài)
-
Flink
檢查點算法的正式名稱是異步屏障快照(asynchronousbarriersnapshotting
)照瘾。該算法大致基于ChandyLamport
分布式快照算法 - 檢查點由
Flink
自動生成,用來在故障發(fā)生時重新處理記錄丧慈,從而修正狀態(tài)析命。Flink
用戶還可以通過另一個特性有意識地管理狀態(tài)版本,這個特性叫作保存點(savepoint
) - 保存點與檢查點的工作方式完全相同逃默,只不過它由用戶通過
Flink
命令行工具或者Web
控制臺手動觸發(fā)鹃愤,而不由Flink
自動觸發(fā)。和檢查點一樣完域,保存點也被保存在穩(wěn)定存儲中 - 對保存點的另一種理解是昼浦,它在明確的時間點保存應(yīng)用程序狀態(tài)的版本
圖5-9:手動觸發(fā)的保存點(以圓圈表示)在不同時間捕獲正在運行的
Flink
應(yīng)用程序的狀態(tài)
圖5-10:使用保存點更新
Flink
應(yīng)用程序的版本。新版本可以從舊版本生成的一個保存點處開始執(zhí)行
- 保存點可用于應(yīng)對流處理作業(yè)在生產(chǎn)環(huán)境中遇到的許多挑戰(zhàn)
- 應(yīng)用程序代碼升級
-
Flink
版本更新 - 維護和遷移
- 假設(shè)模擬與恢復(fù)
-
A/B
測試
圖5-11:在該應(yīng)用程序架構(gòu)中筒主,有狀態(tài)的 Flink 應(yīng)用程序消費來自消息隊列的數(shù)據(jù)关噪,然后將數(shù)據(jù)寫入輸出系統(tǒng),以供查詢 乌妙。底部的詳情圖展示 了 Flink 應(yīng)用程序的內(nèi)部情況
圖5-14:Yahoo!Streaming Benchmark 結(jié)果使兔。橫軸表示每秒的事件吞吐量,以千為單位藤韵∨傲ぃ縱軸表示端到端的99百分位數(shù)延遲,以秒為單位泽艘。
在性能測評中欲险,Spark Streaming 遇到了吞吐量和延遲性難兩全的問題。隨著批處理作業(yè)規(guī)模的增加匹涮,延遲升高天试。如果為了降低延遲而縮減規(guī)模,吞吐量就會減少然低。Storm 和 Flink 則可以在吞吐量增加時維持低延遲
圖5-16:使用高吞吐數(shù)據(jù)生成器的結(jié)果
- 當(dāng)Storm 和 Kafka 一起使用時喜每,應(yīng)用程序可以保持每秒40萬事件的處理速度,并且瓶頸在于 CPU
- 當(dāng) Flink 和 Kafka 一起使用時雳攘,應(yīng)用程序可以保持每秒300萬事件的處理速度带兜,并且瓶頸在于網(wǎng)絡(luò)
- 當(dāng)消除網(wǎng)絡(luò)瓶頸時,F(xiàn)link 應(yīng)用程序可以保持每秒1500萬事件的處理速度
- 在額外的測試中吨灭,消除隊列由 MapR Streams提供刚照,并且采用10個高性能網(wǎng)絡(luò)節(jié)點;Flink 應(yīng)用程序可以保持每秒1000萬事件的處理速度
- 通過避免流處理瓶頸喧兄,同時利用 Flink 的有狀態(tài)流處理能力无畔,可以使吞吐量達到 Storm 的30倍左右 啊楚,同時還能保證
exactly-once
和高可用性
第 6 章 批處理:一種特殊的流處理
- 如果計算結(jié)果不在執(zhí)行過程中連續(xù)生成,而僅在末尾處生成一次檩互,那就是批處理(分批處理數(shù)據(jù))
- 批處理是流處理的一種非常特殊的情況特幔。在流處理是咨演,我們?yōu)閿?shù)據(jù)定義滑動窗口或滾動窗口闸昨,并且在每次窗口滑動或滾動時生成結(jié)果 。批處理則不同薄风,我們定義一個全局窗口饵较,所有的記錄都屬于同一個窗口
圖64:分布式排序的處理階段
進一步使用 Flink
- Https://flink.apache.org有『快速入門』指南,通過例子教你如何使用 Flink 攝取和分析維基百科的編輯日志遭赂。只需花幾分鐘循诉,你就可以開始編寫你的第一個流處理程序了。
- 如果你偏愛視覺效果撇他,可以看看 MapR 公司提供的例子:如何用 Flink 攝取紐約市出租車路線的數(shù)據(jù)流茄猫,并用 Kibana 將它可視化(https://www.mapr.com/blog/essential-guide-streaming-first-processing-apache-flink)