Flink/Blink 原理漫談(二)流表對偶性和distinct詳解

系列文章目錄

Flink/Blink 原理漫談(零)運行時的組件

Flink/Blink 原理漫談(一)時間,watermark詳解

Flink/Blink 原理漫談(二)流表對偶性和distinct詳解

Flink/Blink 原理漫談(三)state 有狀態計算機制 詳解

Flink/Blink 原理漫談(四)window機制詳解

Flink/Blink 原理漫談(五)流式計算的持續查詢實現 詳解

Flink/Blink 原理漫談(六)容錯機制(fault tolerance)詳解



流表對偶性

這部分其實很簡單……不明白爲啥文檔寫的很複雜。
簡單來說,mysql需要進行主備複製,而binlog就是mysql實現主備複製的核心手段。binlog記錄了數據庫上的所有增、刪、更新等操作。binlog中攜帶時間戳,我們將所有表的操作都按時間進行記錄下來形成binlog,而對binlog的event進行回放的過程就是流數據處理的過程,回放的結果恰恰又形成了一張表。也就是表的操作會形成攜帶時間的事件流,對流的處理又會形成一張不斷變化的表,表和流具有等價性,可以互轉。這種流與表的信息無損的互轉,我們稱之爲流表對偶性。

DISTINCT

DISTINCT in SELECT Clause

當DISTINCT用在SELECT Clause中表示對查詢的columns進行去重。

兩種實現

有兩種實現方法:

SELECT DISTINCT expressions
 FROM tables

• DISTINCT - 必須放到開始位置
• expressions - 是N(N>=1)個expression,可以是具體的column,也可以是function等任何合法表達式


SELECT expressions 
•	  FROM tablesGROUP BY expressions ;

這兩種方法的輸出結果一致。

底層原理

對於上面我們說的去重有兩種等效的方式,那麼在Blink 內部採用了哪種方式實現的呢?我們看一下Blink SQL:
SELECT DISTINCT FirstName, LastName FROM distinct_tab_source
的plan如下:

StreamExecGroupAggregate(groupBy=[FirstName, LastName], select=[FirstName, LastName])
  StreamExecExchange(distribution=[hash[FirstName, LastName]])
    StreamExecCalc(select=[FirstName, LastName])
      StreamExecScan(table=[[distinct_tab_source]])

也就是說在Blink 內部利用GROUP BY Clause實現的去重邏輯

DISTINCT in COUNT AGG、

語法

COUNT(DISTINCT expression)

底層原理

CountDistinct 的核心邏輯是對統計列進行去重計數。
• 數據存儲 - 流數據源源不斷的到來,要想知道是否有某個值(對應統計列的值)是否流過,那麼我們必須記錄歷史上已經來過的值,以便去重;
• 數據撤回 - 流上數據的更新我們需要Retract機制處理,其中Retract機制裏面涉及了消息類型,即 "+/-"來標識消息類型。那麼在CountDistinct也要管理“-”的消息,如果已經計數的消息被撤回了,我們需要更新計數統計結果
在這裏插入圖片描述
• + 記錄到來會調用accumulate方法,結合state進行去重計數統計,同時 - 記錄到了會調用 retract 方法,結果state 進行撤回記錄處理。
• +state和-state的數據結構都是 MapView<colType, LONG>, key是存儲col的值,value存儲value的記錄數
• countState是LONG 類型的基礎類型
• -state 實際運行時只有流入的數據正向記錄還沒有到來時候,才需要進行數據存儲(一般很少發生)。
• -state 和 +state (後續版本會合併爲一份state,用value的正負判斷Event類型)
這無疑會導致state越來越大,更多的性能問題會出現,在未來可能會使用基數估計等方法來解決這樣的問題。








發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章