1. 程式人生 > 其它 >Flink 學習 — Flink中的Stream Windows介紹

Flink 學習 — Flink中的Stream Windows介紹

前言

目前有許多資料分析的場景從批處理到流處理的演變, 雖然可以將批處理作為流處理的特殊情況來處理,但是分析無窮集的流資料通常需要思維方式的轉變並且具有其自己的術語(例如,“windowing(視窗化)”、“at-least-once(至少一次)”、“exactly-once(只有一次)” )。

對於剛剛接觸流處理的人來說,這種轉變和新術語可能會非常混亂。 Apache Flink 是一個為生產環境而生的流處理器,具有易於使用的 API,可以用於定義高階流分析程式。

Flink 的 API 在資料流上具有非常靈活的視窗定義,使其在其他開源流處理框架中脫穎而出。

在這篇文章中,我們將討論用於流處理的視窗的概念,介紹 Flink 的內建視窗,並解釋它對自定義視窗語義的支援。

什麼是 Windows?

下面我們結合一個現實的例子來說明。

就拿交通感測器的示例:統計經過某紅綠燈的汽車數量之和?

假設在一個紅綠燈處,我們每隔 15 秒統計一次通過此紅綠燈的汽車數量,如下圖:

可以把汽車的經過看成一個流,無窮的流,不斷有汽車經過此紅綠燈,因此無法統計總共的汽車數量。但是,我們可以換一種思路,每隔 15 秒,我們都將與上一次的結果進行 sum 操作(滑動聚合),如下:

這個結果似乎還是無法回答我們的問題,根本原因在於流是無界的,我們不能限制流,但可以在有一個有界的範圍內處理無界的流資料。

因此,我們需要換一個問題的提法:每分鐘經過某紅綠燈的汽車數量之和?
這個問題,就相當於一個定義了一個 Window(視窗),window 的界限是1分鐘,且每分鐘內的資料互不干擾,因此也可以稱為翻滾(不重合)視窗,如下圖:

第一分鐘的數量為8,第二分鐘是22,第三分鐘是27。。。這樣,1個小時內會有60個window。

再考慮一種情況,每30秒統計一次過去1分鐘的汽車數量之和:

此時,window 出現了重合。這樣,1個小時內會有120個 window。

擴充套件一下,我們可以在某個地區,收集每一個紅綠燈處汽車經過的數量,然後每個紅綠燈處都做一次基於1分鐘的window統計,即並行處理:

它有什麼作用?

通常來講,Window 就是用來對一個無限的流設定一個有限的集合,在有界的資料集上進行操作的一種機制。window 又可以分為基於時間(Time-based)的 window 以及基於數量(Count-based)的 window。

Flink DataStream API 提供了 Time 和 Count 的 window,同時增加了基於 Session 的 window。同時,由於某些特殊的需要,DataStream API 也提供了定製化的 window 操作,供使用者自定義 window。

下面,主要介紹 Time-Based window 以及 Count-Based window,以及自定義的 window 操作,Session-Based Window 操作將會在後續的文章中講到。

Time Windows

正如命名那樣,Time Windows 根據時間來聚合流資料。例如:一分鐘的 tumbling time window 收集一分鐘的元素,並在一分鐘過後對視窗中的所有元素應用於一個函式。

在 Flink 中定義 tumbling time windows(翻滾時間視窗) 和 sliding time windows(滑動時間視窗) 非常簡單:

tumbling time windows(翻滾時間視窗)

輸入一個時間引數

data.keyBy(1)
	.timeWindow(Time.minutes(1)) //tumbling time window 每分鐘統計一次數量和
	.sum(1);

sliding time windows(滑動時間視窗)

輸入兩個時間引數

data.keyBy(1)
	.timeWindow(Time.minutes(1), Time.seconds(30)) //sliding time window 每隔 30s 統計過去一分鐘的數量和
	.sum(1);

有一點我們還沒有討論,即“收集一分鐘的元素”的確切含義,它可以歸結為一個問題,“流處理器如何解釋時間?”

Apache Flink 具有三個不同的時間概念,即 processing time, event time 和 ingestion time。

這裡可以參考我下一篇文章:

《Flink學習》—— Flink 中的幾種 Time 詳解

Count Windows

Apache Flink 還提供計數視窗功能。如果計數視窗設定的為 100 ,那麼將會在視窗中收集 100 個事件,並在新增第 100 個元素時計算視窗的值。

在 Flink 的 DataStream API 中,tumbling count window 和 sliding count window 的定義如下:

tumbling count window

輸入一個時間引數

data.keyBy(1)
	.countWindow(100) //統計每 100 個元素的數量之和
	.sum(1);

sliding count window

輸入兩個時間引數

data.keyBy(1) 
	.countWindow(100, 10) //每 10 個元素統計過去 100 個元素的數量之和
	.sum(1);

Flink 的內建 time window 和 count window 已經覆蓋了大多數應用場景,但是有時候也需要定製視窗邏輯,此時 Flink 的內建的 window 無法解決這些問題。為了還支援自定義 window 實現不同的邏輯,DataStream API 為其視窗機制提供了介面。

下圖描述了 Flink 的視窗機制,並介紹了所涉及的元件:

到達視窗操作符的元素被傳遞給 WindowAssigner。WindowAssigner 將元素分配給一個或多個視窗,可能會建立新的視窗。
視窗本身只是元素列表的識別符號,它可能提供一些可選的元資訊,例如 TimeWindow 中的開始和結束時間。注意,元素可以被新增到多個視窗,這也意味著一個元素可以同時在多個視窗存在。

每個視窗都擁有一個 Trigger(觸發器),該 Trigger(觸發器) 決定何時計算和清除視窗。當先前註冊的計時器超時時,將為插入視窗的每個元素呼叫觸發器。在每個事件上,觸發器都可以決定觸發(即、清除(刪除視窗並丟棄其內容),或者啟動並清除視窗。一個視窗可以被求值多次,並且在被清除之前一直存在。注意,在清除視窗之前,視窗將一直消耗記憶體。

當 Trigger(觸發器) 觸發時,可以將視窗元素列表提供給可選的 Evictor,Evictor 可以遍歷視窗元素列表,並可以決定從列表的開頭刪除首先進入視窗的一些元素。然後其餘的元素被賦給一個計算函式,如果沒有定義 Evictor,觸發器直接將所有視窗元素交給計算函式。

計算函式接收 Evictor 過濾後的視窗元素,並計算視窗的一個或多個元素的結果。 DataStream API 接受不同型別的計算函式,包括預定義的聚合函式,如 sum(),min(),max(),以及 ReduceFunction,FoldFunction 或 WindowFunction。

這些是構成 Flink 視窗機制的元件。 接下來我們逐步演示如何使用 DataStream API 實現自定義視窗邏輯。 我們從 DataStream [IN] 型別的流開始,並使用 key 選擇器函式對其分組,該函式將 key 相同型別的資料分組在一塊。

SingleOutputStreamOperator<xxx> data = env.addSource(...);
data.keyBy()

如何自定義 Window?

1、Window Assigner

負責將元素分配到不同的 window。

Window API 提供了自定義的 WindowAssigner 介面,我們可以實現 WindowAssigner 的

public abstract Collection<W> assignWindows(T element, long timestamp)

方法。同時,對於基於 Count 的 window 而言,預設採用了 GlobalWindow 的 window assigner,例如:

keyBy.window(GlobalWindows.create())

2、Trigger

Trigger 即觸發器,定義何時或什麼情況下移除 window

我們可以指定觸發器來覆蓋 WindowAssigner 提供的預設觸發器。 請注意,指定的觸發器不會新增其他觸發條件,但會替換當前觸發器。

3、Evictor(可選)

驅逐者,即保留上一 window 留下的某些元素

4、通過 apply WindowFunction 來返回 DataStream 型別資料。

利用 Flink 的內部視窗機制和 DataStream API 可以實現自定義的視窗邏輯,例如 session window。

結論

對於現代流處理器來說,支援連續資料流上的各種型別的視窗是必不可少的。 Apache Flink 是一個具有強大功能集的流處理器,包括一個非常靈活的機制,可以在連續資料流上構建視窗。 Flink 為常見場景提供內建的視窗運算子,以及允許使用者自定義視窗邏輯。

參考

1、 https://flink.apache.org/news/2015/12/04/Introducing-windows.html

2、 https://blog.csdn.net/lmalds/article/details/51604501

原文地址:http://www.54tianzhisheng.cn/2018/12/08/Flink-Stream-Windows/

.