公司主要做的事物聯網和數字孿生,下半年我們項目要接入大數據,要進行處理再整合Drools,進行規則預警。最近幾個月一直在忙pmp考試和平時工作,也沒有進行學習整理,最近就開始學習flink和kafka,記點筆記。
Flink組件棧
一個計算框架要有長遠的發展,必須打造一個完整的 Stack。只有上層有了具體的應用,並能很好的發揮計算框架本身的優勢,那么這個計算框架才能吸引更多的資源,才會更快的進步。所以 Flink 也在努力構建自己的 Stack。
Flink分層的組件棧如下圖所示:每一層所包含的組件都提供了特定的抽象,用來服務於上層組件。
各層詳細介紹:
-
物理部署層:Flink 支持本地運行、能在獨立集群或者在被 YARN 管理的集群上運行,也能部署在雲上,該層主要涉及Flink的部署模式,目前Flink支持多種部署模式:本地、集群(Standalone、YARN)、雲(GCE/EC2)、Kubenetes。Flink能夠通過該層能夠支持不同平台的部署,用戶可以根據需要選擇使用對應的部署模式。
-
Runtime核心層:Runtime層提供了支持Flink計算的全部核心實現,為上層API層提供基礎服務,該層主要負責對上層不同接口提供基礎服務,也是Flink分布式計算框架的核心實現層,支持分布式Stream作業的執行、JobGraph到ExecutionGraph的映射轉換、任務調度等。將DataSteam和DataSet轉成統一的可執行的Task Operator,達到在流式引擎下同時處理批量計算和流式計算的目的。
-
API&Libraries層:Flink 首先支持了 Scala 和 Java 的 API,Python也正在測試中。DataStream、DataSet、Table、SQL API,作為分布式數據處理框架,Flink同時提供了支撐計算和批計算的接口,兩者都提供給用戶豐富的數據處理高級API,例如Map、FlatMap操作等,也提供比較低級的Process Function API,用戶可以直接操作狀態和時間等底層數據。
-
擴展庫:Flink 還包括用於復雜事件處理的CEP,機器學習庫FlinkML,圖處理庫Gelly等。Table 是一種接口化的 SQL 支持,也就是 API 支持(DSL),而不是文本化的SQL解析和執行。
Flink基石
Flink之所以能這么流行,離不開它最重要的四個基石:Checkpoint、State、Time、Window。
-
Checkpoint
這是Flink最重要的一個特性。
Flink基於Chandy-Lamport算法實現了一個分布式的一致性的快照,從而提供了一致性的語義。
Chandy-Lamport算法實際上在1985年的時候已經被提出來,但並沒有被很廣泛的應用,而Flink則把這個算法發揚光大了。
Spark最近在實現Continue streaming,Continue
streaming的目的是為了降低處理的延時,其也需要提供這種一致性的語義,最終也采用了Chandy-Lamport這個算法,說明Chandy-Lamport算法在業界得到了一定的肯定。 -
State
提供了一致性的語義之后,Flink為了讓用戶在編程時能夠更輕松、更容易地去管理狀態,還提供了一套非常簡單明了的State
API,包括里面的有ValueState、ListState、MapState,近期添加了BroadcastState,使用State
API能夠自動享受到這種一致性的語義。 -
Time
除此之外,Flink還實現了Watermark的機制,能夠支持基於事件的時間的處理,能夠容忍遲到/亂序的數據。
-
Window
另外流計算中一般在對流數據進行操作之前都會先進行開窗,即基於一個什么樣的窗口上做這個計算。Flink提供了開箱即用的各種窗口,比如滑動窗口、滾動窗口、會話窗口以及非常靈活的自定義的窗口。
Flink用武之地
http://www.liaojiayi.com/flink-IoT/
https://flink.apache.org/zh/usecases.html
從很多公司的應用案例發現,其實Flink主要用在如下三大場景:
Event-driven Applications【事件驅動】
事件驅動型應用是一類具有狀態的應用,它從一個或多個事件流提取數據,並根據到來的事件觸發計算、狀態更新或其他外部動作。
事件驅動型應用是在計算存儲分離的傳統應用基礎上進化而來。
在傳統架構中,應用需要讀寫遠程事務型數據庫。
相反,事件驅動型應用是基於狀態化流處理來完成。在該設計中,數據和計算不會分離,應用只需訪問本地(內存或磁盤)即可獲取數據。
系統容錯性的實現依賴於定期向遠程持久化存儲寫入checkpoint。下圖描述了傳統應用和事件驅動型應用架構的區別。
從某種程度上來說,所有的實時的數據處理或者是流式數據處理都應該是屬於Data Driven,流計算本質上是Data Driven計算。應用較多的如風控系統,當風控系統需要處理各種各樣復雜的規則時,Data Driven就會把處理的規則和邏輯寫入到Datastream 的API 或者是ProcessFunction 的API中,然后將邏輯抽象到整個Flink引擎,當外面的數據流或者是事件進入就會觸發相應的規則,這就是Data Driven的原理。在觸發某些規則后,Data Driven會進行處理或者是進行預警,這些預警會發到下游產生業務通知,這是Data Driven的應用場景,Data Driven 在應用上更多應用於復雜事件的處理。
典型實例:
-
欺詐檢測(Fraud detection)
-
異常檢測(Anomaly detection)
-
基於規則的告警(Rule-based alerting)
-
業務流程監控(Business process monitoring)
-
Web應用程序(社交網絡)
Data Analytics Applications【數據分析】
數據分析任務需要從原始數據中提取有價值的信息和指標。如下圖所示,Apache Flink 同時支持流式及批量分析應用。
Data Analytics Applications包含Batch analytics(批處理分析)和Streaming analytics(流處理分析)
Batch analytics可以理解為周期性查詢:Batch Analytics 就是傳統意義上使用類似於Map Reduce、Hive、Spark Batch等,對作業進行分析、處理、生成離線報表。比如Flink應用凌晨從Recorded Events中讀取昨天的數據,然后做周期查詢運算,最后將數據寫入Database或者HDFS,或者直接將數據生成報表供公司上層領導決策使用。
Streaming analytics可以理解為連續性查詢:比如實時展示雙十一天貓銷售GMV(Gross Merchandise Volume成交總額),用戶下單數據需要實時寫入消息隊列,Flink應用源源不斷讀取數據做實時計算,然后不斷的將數據更新至Database或者K-VStore,最后做大屏實時展示。
典型實例
-
電信網絡質量監控
-
移動應用中的產品更新及實驗評估分析
-
消費者技術中的實時數據即席分析
-
大規模圖分析
Data Pipeline Applications【數據管道】
什么是數據管道?
提取-轉換-加載(ETL)是一種在存儲系統之間進行數據轉換和遷移的常用方法。
ETL 作業通常會周期性地觸發,將數據從事務型數據庫拷貝到分析型數據庫或數據倉庫。
數據管道和 ETL作業的用途相似,都可以轉換、豐富數據,並將其從某個存儲系統移動到另一個。
但數據管道是以持續流模式運行,而非周期性觸發。因此數據管道支持從一個不斷生成數據的源頭讀取記錄,並將它們以低延遲移動到終點。
例如:數據管道可以用來監控文件系統目錄中的新文件,並將其數據寫入事件日志;另一個應用可能會將事件流物化到數據庫或增量構建和優化查詢索引。
和周期性 ETL 作業相比,持續數據管道可以明顯降低將數據移動到目的端的延遲。此外,由於它能夠持續消費和發送數據,因此用途更廣,支持用例更多。
下圖描述了周期性ETL作業和持續數據管道的差異。
Periodic ETL:比如每天凌晨周期性的啟動一個Flink ETL Job,讀取傳統數據庫中的數據,然后做ETL,最后寫入數據庫和文件系統。
Data Pipeline:比如啟動一個Flink實時應用,數據源(比如數據庫、Kafka)中的數據不斷的通過Flink Data Pipeline流入或者追加到數據倉庫(數據庫或者文件系統),或者Kafka消息隊列。
Data Pipeline的核心場景類似於數據搬運並在搬運的過程中進行部分數據清洗或者處理,而整個業務架構圖的左邊是Periodic ETL,它提供了流式ETL
或者實時ETL,能夠訂閱消息隊列的消息並進行處理,清洗完成后實時寫入到下游的Database或File system 中。
典型實例
- 電子商務中的持續 ETL(實時數倉)
當下游要構建實時數倉時,上游則可能需要實時的Stream ETL。這個過程會進行實時清洗或擴展數據,清洗完成后寫入到下游的實時數倉的整個鏈路中,可保證數據查詢的時效性,形成實時數據采集、實時數據處理以及下游的實時Query。
- 電子商務中的實時查詢索引構建(搜索引擎推薦)
搜索引擎這塊以淘寶為例,當賣家上線新商品時,后台會實時產生消息流,該消息流經過Flink系統時會進行數據的處理、擴展。然后將處理及擴展后的數據生成實時索引,寫入到搜索引擎中。這樣當淘寶賣家上線新商品時,能在秒級或者分鍾級實現搜索引擎的搜索。
Flink的優勢
- 主要原因
-
Flink 具備統一的框架處理有界和無界兩種數據流的能力
-
部署靈活,Flink 底層支持多種資源調度器,包括Yarn、Kubernetes 等。Flink自身帶的Standalone 的調度器,在部署上也十分靈活。
-
極高的可伸縮性,可伸縮性對於分布式系統十分重要,阿里巴巴雙11大屏采用Flink處理海量數據,使用過程中測得Flink 峰值可達17 億條/秒。
-
極致的流式處理性能。Flink 相對於Storm最大的特點是將狀態語義完全抽象到框架中,支持本地狀態讀取,避免了大量網絡IO,可以極大提升狀態存取的性能。
- 其他更多的原因:
- 同時支持高吞吐、低延遲、高性能
Flink是目前開源社區中唯一一套集高吞吐、低延遲、高性能三者於一身的分布式流式數據處理框架。
Spark只能兼顧高吞吐和高性能特性,無法做到低延遲保障,因為Spark是用批處理來做流處理
Storm 只能支持低延時和高性能特性,無法滿足高吞吐的要求下圖顯示了 Apache Flink 與 Apache Storm 在完成流數據清洗的分布式任務的性能對比。
支持事件時間(Event Time)概念
在流式計算領域中,窗口計算的地位舉足輕重,但目前大多數框架窗口計算采用的都是系統時間(ProcessTime),也就是事件傳輸到計算框架處理時,系統主機的當前時間。
Flink 能夠支持基於事件時間(Event Time)語義進行窗口計算
這種基於事件驅動的機制使得事件即使亂序到達甚至延遲到達,流系統也能夠計算出精確的結果,保持了事件原本產生時的時序性,盡可能避免網絡傳輸或硬件系統的影響。
支持有狀態計算
Flink1.4開始支持有狀態計算
所謂狀態就是在流式計算過程中將算子的中間結果保存在內存或者文件系統中,等下一個事件進入算子后可以從之前的狀態中獲取中間結果,計算當前的結果,從而無須每次都基於全部的原始數據來統計結果,極大的提升了系統性能,狀態化意味着應用可以維護隨着時間推移已經產生的數據聚合
支持高度靈活的窗口(Window)操作
Flink 將窗口划分為基於 Time 、Count、Session、以及Data-Driven等類型的窗口操作,窗口可以用靈活的觸發條件定制化來達到對復雜的流傳輸模式的支持,用戶可以定義不同的窗口觸發機制來滿足不同的需求
基於輕量級分布式快照(Snapshot/Checkpoints)的容錯機制
Flink能夠分布運行在上千個節點上,通過基於分布式快照技術的Checkpoints,將執行過程中的狀態信息進行持久化存儲,一旦任務出現異常停止,Flink
能夠從 Checkpoints 中進行任務的自動恢復,以確保數據處理過程中的一致性
Flink的容錯能力是輕量級的,允許系統保持高並發,同時在相同時間內提供強一致性保證。
基於 JVM 實現的獨立的內存管理
Flink實現了自身管理內存的機制,通過使用散列,索引,緩存和排序有效地進行內存管理,通過序列化/反序列化機制將所有的數據對象轉換成二進制在內存中存儲,降低數據存儲大小的同時,更加有效的利用空間。使其獨立於Java 的默認垃圾收集器,盡可能減少 JVM GC 對系統的影響。
SavePoints 保存點
對於 7 * 24小時運行的流式應用,數據源源不斷的流入,在一段時間內應用的終止有可能導致數據的丟失或者計算結果的不准確。比如集群版本的升級,停機運維操作等。值得一提的是,Flink 通過SavePoints技術將任務執行的快照保存在存儲介質上,當任務重啟的時候,可以從事先保存的SavePoints 恢復原有的計算狀態,使得任務繼續按照停機之前的狀態運行。
Flink保存點提供了一個狀態化的版本機制,使得能以無丟失狀態和最短停機時間的方式更新應用或者回退歷史數據。
靈活的部署方式,支持大規模集群
Flink 被設計成能用上千個點在大規模集群上運行除了支持獨立集群部署外,Flink 還支持 YARN 和Mesos 方式部署。
Flink 的程序內在是並行和分布式的
數據流可以被分區成 stream partitions,operators 被划分為operator subtasks;這些 subtasks 在不同的機器或容器中分不同的線程獨立運行;
operator subtasks 的數量就是operator的並行計算數,不同的 operator階段可能有不同的並行數;如下圖所示,source operator 的並行數為 2,但最后的 sink operator 為1;
豐富的庫
Flink 擁有豐富的庫來進行機器學習,圖形處理,關系數據處理等。
流處理 VS 批處理
- 數據的時效性
日常工作中,我們一般會先把數據存儲在表,然后對表的數據進行加工、分析。既然先存儲在表中,那就會涉及到時效性概念。
如果我們處理以年,月為單位的級別的數據處理,進行統計分析,個性化推薦,那么數據的的最新日期離當前有幾個甚至上月都沒有問題。但是如果我們處理的是以天為級別,或者一小時甚至更小粒度的數據處理,那么就要求數據的時效性更高了。比如:
- 對網站的實時監控
這些場景需要工作人員立即響應,這樣的場景下,傳統的統一收集數據,再存到數據庫中,再取出來進行分析就無法滿足高時效性的需求了。
- 流式計算和批量計算
- Batch Analytics,右邊是 Streaming Analytics。批量計算:統一收集數據->存儲到DB->對數據進行批量處理,就是傳統意義上使用類似於 Map Reduce、Hive、Spark Batch 等,對作業進行分析、處理、生成離線報表
- Streaming Analytics流式計算,顧名思義,就是對數據流進行處理,如使用流式分析引擎如Storm,Flink 實時處理分析數據,應用較多的場景如實時大屏、實時報表。
它們的主要區別是:
-
與批量計算那樣慢慢積累數據不同,流式計算立刻計算,數據持續流動,計算完之后就丟棄。
-
批量計算是維護一張表,對表進行實施各種計算邏輯。流式計算相反,是必須先定義好計算邏輯,提交到流式計算系統,這個計算作業邏輯在整個運行期間是不可更改的。
-
計算結果上,批量計算對全部數據進行計算后傳輸結果,流式計算是每次小批量計算后,結果可以立刻實時化展現。
-
流批統一
在大數據處理領域,批處理任務與流處理任務一般被認為是兩種不同的任務,一個大數據框架一般會被設計為只能處理其中一種任務:
MapReduce只支持批處理任務;Storm只支持流處理任務;Spark Streaming采用micro-batch架構,本質上還是基於Spark批處理對流式數據進行處理
Flink通過靈活的執行引擎,能夠同時支持批處理任務與流處理任務
在執行引擎這一層,流處理系統與批處理系統最大不同在於節點間的數據傳輸方式:
1.對於一個流處理系統,其節點間數據傳輸的標准模型是:當一條數據被處理完成后,序列化到緩存中,然后立刻通過網絡傳輸到下一個節點,由下一個節點繼續處理
2.對於一個批處理系統,其節點間數據傳輸的標准模型是:當一條數據被處理完成后,序列化到緩存中,並不會立刻通過網絡傳輸到下一個節點,當緩存寫滿,就持久化到本地硬盤上,當所有數據都被處理完成后,才開始將處理后的數據通過網絡傳輸到下一個節點這兩種數據傳輸模式是兩個極端,對應的是流處理系統對低延遲的要求和批處理系統對高吞吐量的要求Flink的執行引擎采用了一種十分靈活的方式,同時支持了這兩種數據傳輸模型:Flink以固定的緩存塊為單位進行網絡數據傳輸,用戶可以通過設置緩存塊超時值指定緩存塊的傳輸時機。如果緩存塊的超時值為0,則Flink的數據傳輸方式類似上文所提到流處理系統的標准模型,此時系統可以獲得最低的處理延遲
如果緩存塊的超時值為無限大/-1,則Flink的數據傳輸方式類似上文所提到批處理系統的標准模型,此時系統可以獲得最高的吞吐量同時緩存塊的超時值也可以設置為0到無限大之間的任意值。緩存塊的超時閾值越小,則Flink流處理執行引擎的數據處理延遲越低,但吞吐量也會降低,反之亦然。通過調整緩存塊的超時閾值,用戶可根據需求靈活地權衡系統延遲和吞吐量
默認情況下,流中的元素並不會一個一個的在網絡中傳輸,而是緩存起來伺機一起發送(默認為32KB,通過taskmanager.memory.segment-size設置),這樣可以避免導致頻繁的網絡傳輸,提高吞吐量,但如果數據源輸入不夠快的話會導致后續的數據處理延遲,所以可以使用env.setBufferTimeout(默認100ms),來為緩存填入設置一個最大等待時間。等待時間到了之后,即使緩存還未填滿,緩存中的數據也會自動發送。
-
timeoutMillis > 0 表示最長等待 timeoutMillis 時間,就會flush
-
timeoutMillis = 0 表示每條數據都會觸發flush,直接將數據發送到下游,相當於沒有Buffer了(避免設置為0,可能導致性能下降)
-
timeoutMillis = -1 表示只有等到 buffer滿了或CheckPoint的時候,才會flush。相當於取消了 timeout 策略
總結:
Flink以緩存塊為單位進行網絡數據傳輸,用戶可以設置緩存塊超時時間和緩存塊大小來控制緩沖塊傳輸時機,從而控制Flink的延遲性和吞吐量