中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

如何分析Flink窗口的應用與實現

發布時間:2021-11-15 14:42:10 來源:億速云 閱讀:126 作者:柒染 欄目:大數據

這篇文章給大家介紹如何分析Flink窗口的應用與實現,內容非常詳細,感興趣的小伙伴們可以參考借鑒,希望對大家能有所幫助。



整體思路與學習路徑

當我們碰到一項新的技術時,我們應該怎樣去學習并應用它呢?在我個人看來,有這樣一個學習的路徑,應該把它拆成應用和實現兩塊。首先應該從它的應用入手,然后再深入它的實現。


應用主要分為三個部分,首先應該了解它的應用場景,比如窗口的一些使用場景。然后,進一步地我們去了解它的編程接口,最后再深入了解它的一些抽象概念。因為一個框架或一項技術,肯定有它的編程接口和抽象概念來組成它的編程模型。我們可以通過查看文檔的方式來熟悉它的應用。在對應用這三個部分有了初步的了解后,我們就可以通過閱讀代碼的方式去了解它的一些實現了。

實現部分也分三個階段,首先從工作流程開始,可以通過 API 層面不斷的下鉆來了解它的工作流程。接下來是它整體的設計模式,通常對一些框架來說,如果能構建一個比較成熟的生態,一定是在設計模式上有一些獨特的地方,使其有一個比較好的擴展性。最后是它的數據結構和算法,因為為了能夠處理海量數據并達到高性能,它的數據結構和算法一定有獨到之處。我們可以做些深入了解。

以上大概是我們學習的一個路徑。從實現的角度可以反哺到應用上來,通常在應用當中,剛接觸某個概念的時候會有一些疑惑。當我們對實現有一些了解之后,應用中的這些疑惑就會迎刃而解。


     
為什么要關心實現      
     

舉個例子:

如何分析Flink窗口的應用與實現


看了這個例子我們可能會有些疑惑:

  • ReduceFunction 為什么不用計算每個 key 的聚合值?
  • 當 key 基數很大時,如何有效地觸發每個 key 窗口計算?
  • 窗口計算的中間結果如何存儲,何時被清理?
  • 窗口計算如何容忍 late data ?

當你了解了實現部分再回來看應用這部分,可能就有種醍醐灌頂的感覺。

應用場景與編程模型


     

實時數倉的典型架構


如何分析Flink窗口的應用與實現


■ 第一種最簡單架構,ODS 層的 Kafka 數據經過 Flink 的 ETL 處理后寫入 DW 層的 Kafka,再通過 Flink 聚合寫入 ADS 層的 MySQL 中,做這樣一個實時報表展現。

缺點:  由于 MySQL 存儲數據有限,所以聚合的時間粒度不能太細,維度組合不能太多。

■ 第二種架構相對于第一種引入了 OLAP 引擎,同時也不用 Flink 來做聚合,通過 Druid 的 Rollup 來做聚合。

缺點:  因為 Druid 是一個存儲和查詢引擎,不是計算引擎。當數據量巨大時,比如每天上百億、千億的數據量,會加劇 Druid 的導入壓力。

■ 第三種架構在第二種基礎上,采用 Flink 來做聚合計算寫入 Kafka,最終寫入 Druid。

缺點:  當窗口粒度比較長時,結果輸出會有延遲。

■ 第四種架構在第三種基礎上,結合了 Flink 聚合和 Druid Rollup。Flink 可以做輕度的聚合,Druid 做 Rollup 的匯總。好處是 Druid 可以實時看到 Flink 的聚合結果。

           

Window 應用場景



 

如何分析Flink窗口的應用與實現


■ 聚合統計:  從 Kafka 讀取數據,根據不同的維度做1分鐘或5分鐘的聚合計算,然后結果寫入 MySQL 或 Druid 中。

■ 記錄合并:  對多個 Kafka 數據源在一定的窗口范圍內做合并,結果寫入 ES。例如:用戶的一些行為數據,針對每個用戶,可以對其行為做一定的合并,減少寫入下游的數據量,降低 ES 的寫入壓力。

■ 雙流 join:  針對雙流 join 的場景,如果全量 join 的話,成本開銷會非常大。所以就要考慮基于窗口來做 join。


     

Window 抽象概念


如何分析Flink窗口的應用與實現


■ TimestampAssigner:  時間戳分配器,假如我們使用的是 EventTime 時間語義,就需要通過 TimestampAssigner 來告訴Flink 框架,元素的哪個字段是事件時間,用于后面的窗口計算。

■ KeySelector:  Key 選擇器,用來告訴 Flink 框架做聚合的維度有哪些。

■ WindowAssigner:  窗口分配器,用來確定哪些數據被分配到哪些窗口。

■ State:  狀態,用來存儲窗口內的元素,如果有 AggregateFunction,則存儲的是增量聚合的中間結果。

■ AggregateFunction(可選):  增量聚合函數,主要用來做窗口的增量計算,減輕窗口內 State 的存儲壓力。

■ Trigger:  觸發器,用來確定何時觸發窗口的計算。

■ Evictor(可選)  :驅逐器,用于在窗口函數計算之前(后)對滿足驅逐條件的數據做過濾。

■ WindowFunction  :窗口函數,用來對窗口內的數據做計算。

■ Collector  :收集器,用來將窗口的計算結果發送到下游。

上圖中紅色部分都是可以自定義的模塊,通過自定義這些模塊的組合,我們可以實現高級的窗口應用。同時 Flink 也提供了一些內置的實現,可以用來做一些簡單應用。

           

Window 編程接口



 
  
    
  
  
  
stream        .assignTimestampsAndWatermarks(…)     <-    TimestampAssigner  .keyBy(...)                           <-    KeySelector         .window(...)                          <-    WindowAssigner          [.trigger(...)]                       <-    Trigger           [.evictor(...)]                       <-    Evictor  .reduce/aggregate/process()           <-    Aggregate/Window function
           

                       
首先我們先指定時間戳和 Watermark 如何生成;然后選擇需要聚合的維度的 Key;再選擇一個窗口和選擇用什么樣的觸發器來觸發窗口計算,以及選擇驅逐器做什么樣的過濾;最后確定窗口應該做什么樣計算。

下面是一個示例:

如何分析Flink窗口的應用與實現


接下來我們詳細看下每個模塊。

■ Window Assigner

如何分析Flink窗口的應用與實現

總結一下主要有3類窗口:

  • Time Window
  • Count Window
  • Custom Window

■  Window Trigger

Trigger 是一個比較重要的概念,用來確定窗口什么時候觸發計算。

Flink 內置了一些 Trigger 如下圖:

如何分析Flink窗口的應用與實現


■ Trigger 示例

如何分析Flink窗口的應用與實現


假如我們定義一個5分鐘的基于 EventTime 的滾動窗口,定義一個每2分觸發計算的 Trigger,有4條數據事件時間分別是20:01、20:02、20:03、20:04,對應的值分別是1、2、3、2,我們要對值做 Sum 操作。  

初始時,State 和 Result 中的值都為0。

如何分析Flink窗口的應用與實現


當第一條數據在20:01進入窗口時,State 的值為1,此時還沒有到達 Trigger 的觸發時間。

如何分析Flink窗口的應用與實現


第二條數據在20:02進入窗口,State 中的值為1+2=3,此時達到2分鐘滿足 Trigger 的觸發條件,所以 Result 輸出結果為3。

如何分析Flink窗口的應用與實現


第三條數據在20:03進入窗口,State 中的值為3+3 = 6,此時未達到 Trigger 觸發條件,沒有結果輸出。

如何分析Flink窗口的應用與實現


第四條數據在20:04進入窗口,State中的值更新為6+2=8,此時又到了2分鐘達到了 Trigger 觸發時間,所以輸出結果為8。如果我們把結果輸出到支持 update 的存儲,比如 MySQL,那么結果值就由之前的3更新成了8。

■ 問題:如果 Result 只能 append?

如何分析Flink窗口的應用與實現


如果 Result 不支持 update 操作,只能 append 的話,則會輸出2條記錄,在此基礎上再做計算處理就會引起錯誤。

這樣就需要 PurgingTrigger 來處理上面的問題。

■ PurgingTrigger 的應用

如何分析Flink窗口的應用與實現


和上面的示例一樣,唯一的不同是在 ContinuousEventTimeTrigger 外面包裝了一個 PurgingTrigger,其作用是在 ContinuousEventTimeTrigger 觸發窗口計算之后將窗口的 State 中的數據清除。

再看下流程:

如何分析Flink窗口的應用與實現


前兩條數據先后于20:01和20:02進入窗口,此時 State 中的值更新為3,同時到了Trigger的觸發時間,輸出結果為3。

如何分析Flink窗口的應用與實現


由于 PurgingTrigger 的作用,State 中的數據會被清除。

如何分析Flink窗口的應用與實現


當后兩條數據進入窗口之后,State 重新從0開始累計并更新為5,輸出結果為5。

由于結果輸出是 append 模式,會輸出3和5兩條數據,然后再做 Sum 也能得到正確的結果。

上面就是 PurgingTrigger 的一個簡單的示例,它還支持很多有趣的玩法。

■ DeltaTrigger 的應用

有這樣一個車輛區間測試的需求,車輛每分鐘上報當前位置與車速,每行進10公里,計算區間內最高車速。

如何分析Flink窗口的應用與實現


首先需要考慮的是如何來劃分窗口,它不是一個時間的窗口,也不是一個基于數量的窗口。用傳統的窗口實現比較困難,這種情況下我們考慮使用 DeltaTrigger 來實現。

下面是簡單的代碼實現:

如何分析Flink窗口的應用與實現


如何提取時間戳和生成水印,以及選擇聚合維度就不贅述了。這個場景不是傳統意義上的時間窗口或數量窗口,可以創建一個 GlobalWindow,所有數據都在一個窗口中,我們通過定義一個 DeltaTrigger,并設定一個閾值,這里是10000(米)。每個元素和上次觸發計算的元素比較是否達到設定的閾值,這里比較的是每個元素上報的位置,如果達到了10000(米),那么當前元素和上一個觸發計算的元素之間的所有元素落在同一個窗口里計算,然后可以通過 Max 聚合計算出最大的車速。

■ 思考點
上面這個例子中我們通過 GlobalWindow 和 DeltaTrigger 來實現了自定義的 Window Assigner 的功能。  對于一些復雜的窗口,我們還可以自定義 WindowAssigner,但實現起來不一定簡單,倒不如利用 GlobalWindow 和自定義 Trigger 來達到同樣的效果。  

下面這個是 Flink 內置的 CountWindow 的實現,也是基于 GlobalWindow 和 Trigger 來實現的。

如何分析Flink窗口的應用與實現


■ Window Evictor

Flink 內置了一些 Evictor 的實現。

如何分析Flink窗口的應用與實現


 TimeEvictor 的應用

基于上面的區間測速的場景,每行進10公里,計算區間內最近15分鐘最高車速。

如何分析Flink窗口的應用與實現


實現上只是在前面基礎上增加了 Evictor 的使用,過濾掉窗口最后15分鐘之前的數據。

如何分析Flink窗口的應用與實現


  Window Function

Flink 內置的 WindowFunction 有兩種類型,第一種是 AggregateFunction,它是高級別的抽象,主要用來做增量聚合,每來一條元素都做一次聚合,這樣狀態里只需要存最新的聚合值。

  • 優點:增量聚合,實現簡單。
  • 缺點:輸出只有一個聚合值,使用場景比較局限。

如何分析Flink窗口的應用與實現


第二種是 ProcessWindowFunction,它是低級別的抽象用來做全量聚合,每來一條元素都存在狀態里面,只有當窗口觸發計算時才會調用這個函數。

如何分析Flink窗口的應用與實現


  • 優點:可以獲取到窗口內所有數據的迭代器,實現起來比較靈活;可以獲取到聚合的  Key 以及可以從上下文 Context 中獲取窗口的相關信息。
  • 缺點:需要存儲窗口內的全量數據,State 的壓力較大。

同時我們可以把這兩種方式結合起來使用,通過 AggregateFunction 做增量聚合,減少中間狀態的壓力。通過 ProcessWindowFunction 來輸出我們想要的信息,比如聚合的 Key 以及窗口的信息。

工作流程和實現機制

上一節我們介紹了窗口的一些抽象的概念,包括它的編程接口,通過一些簡單的示例介紹了每個抽象概念的的用法。  

這一節我們深入的研究以下窗口底層是怎么實現的。


     

WindowOperator 工作流程


首先看下 WindowOperator 的工作流程,代碼做了一些簡化,只保留了核心步驟。

如何分析Flink窗口的應用與實現


主要包括以下8個步驟:

1. 獲取 element 歸屬的 windows
2. 獲取 element 對應的 key
3. 如果 late data,跳過
4. 將 element 存入 window state
5. 判斷 element 是否觸發 trigger
6. 獲取 window state,注入 window function
7. 清除 window state
8. 注冊 timer,到窗口結束時間清理 window

           

Window State


前面提到的增量聚合計算和全量聚合計算,這兩個場景所應用的 State 是不一樣的。

如果是全量聚合,元素會添加到 ListState 當中,當觸發窗口計算時,再把 ListState 中所有元素傳遞給窗口函數。

如何分析Flink窗口的應用與實現


如果是增量計算,使用的是 AggregatingState,每條元素進來會觸發 AggregateTransformation 的計算。

如何分析Flink窗口的應用與實現


看下 AggregateTransformation 的實現,它會調用我們定義的 AgregateFunction 中的 createAccumulator 方法和 add 方法并將 add 的結果返回,所以 State 中存儲的就是 accumulator 的值,所以比較輕量級。

如何分析Flink窗口的應用與實現



     

Window Function


在觸發窗口計算時會將窗口中的狀態傳遞給 emitWindowContents 方法。這里會調用我們定義的窗口函數中的 process 方法,將當前的 Key、Window、上下文 Context、窗口的內容作為參數傳給它。在此之前和之后會分別調用 evictBefore 和evictAfter 方法把一些元素過濾掉。最終會調用 windowState 的 clear 方法,再把過濾之后的記錄存到 windowState 中去。從而達到 evictor 過濾元素的效果。

如何分析Flink窗口的應用與實現



     

Window Trigger


最后看下 Trigger 的實現原理。當我們有大量的 Key,同時每個 Key 又屬于多個窗口時,我們如何有效的觸發窗口的計算呢?

Flink 利用定時器來保證窗口的觸發,通過優先級隊列來存儲定時器。隊列頭的定時器表示離當前時間最近的一個,如果當前定時器比隊列頭的定時器時間還要早,則取消掉隊列頭的定時器,把當前的時間注冊進去。

如何分析Flink窗口的應用與實現

如何分析Flink窗口的應用與實現


當這次定時器觸發之后,再從優先級隊列中取下一個 Timer,去調用 trigger 處理的函數,再把下一個 Timer 的時間注冊為定時器。這樣就可以循環迭代下去。

如何分析Flink窗口的應用與實現

本文主要分享了 Flink 窗口的應用與實現。首先介紹了學習一項新技術的整體思路與學習路徑,從應用入手慢慢深入它的實現。然后介紹了實時數倉的典型架構發展歷程,之后從窗口的應用場景、抽象概念、編程結構詳細說明了窗口的各個組成部分。并通過一些示例詳細展示了各個概念之間配合使用可以滿足什么樣的使用場景。最后深入窗口的實現,從源碼層面說明了窗口各模塊的工作流程。

關于如何分析Flink窗口的應用與實現就分享到這里了,希望以上內容可以對大家有一定的幫助,可以學到更多知識。如果覺得文章不錯,可以把它分享出去讓更多的人看到。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

毕节市| 酒泉市| 融水| 娄烦县| 明溪县| 雷波县| 广饶县| 讷河市| 通河县| 新疆| 唐河县| 龙口市| 海城市| 南昌市| 泗阳县| 文山县| 东山县| 合川市| 炉霍县| 灵石县| 宜州市| 西贡区| 溧阳市| 呼玛县| 汉源县| 舟曲县| 合作市| 锡林郭勒盟| 宣化县| 栾城县| 阿城市| 疏附县| 澄迈县| 汝州市| 信丰县| 滁州市| 灵台县| 砀山县| 威远县| 吉安县| 扶风县|