數棧技術分享:用短平快的方式告訴你Flink-SQL的擴充套件實現

數棧DTinsight發表於2021-06-17

數棧是雲原生—站式資料中臺PaaS,我們在github和gitee上有一個有趣的開源專案:FlinkX,FlinkX是一個基於Flink的批流統一的資料同步工具,既可以採集靜態的資料,也可以採集實時變化的資料,是全域、異構、批流一體的資料同步引擎。大家喜歡的話請給我們點個 star!star!star!

github開源專案:

gitee開源專案:https://gitee.com/dtstack_dev_0/flinkx


首先,本文所述均基於 flink 1.5.4

一、我們為什麼擴充套件Flink-SQL?

由於Flink 本身SQL語法並不提供在對接輸入源和輸出目的的SQL語法。資料開發在使用的過程中需要根據其提供的Api介面編寫Source和 Sink, 異常繁瑣,不僅需要了解FLink 各類Operator的API,還需要對各個元件的相關呼叫方式有了解(比如kafka,redis,mongo,hbase等),並且在需要關聯到外部資料來源的時候沒有提供SQL相關的實現方式,因此資料開發直接使用Flink編寫SQL作為實時的資料分析時需要較大的額外工作量。

我們的目的是在使用Flink-SQL的時候只需要關心做什麼,而不需要關心怎麼做。不需要過多的關心程式的實現,專注於業務邏輯。

接下來,我們一起來看下Flink-SQL的擴充套件實現吧!

二、擴充套件了哪些flink相關sql

1、建立源表語句

2、建立輸出表語句

3、建立自定義函式

4、維表關聯

三、各個模組是如何翻譯到flink的實現

1、如何將建立源表的sql語句轉換為flink的operator

Flink中表的都會對映到Table這個類。然後呼叫註冊方法將Table註冊到environment。

StreamTableEnvironment.registerTable(tableName, table);

當前我們只支援kafka資料來源。Flink本身有讀取kafka 的實現類, FlinkKafkaConsumer09,所以只需要根據指定引數例項化出該物件。並呼叫註冊方法註冊即可。

另外需要注意在flink sql經常會需要用到rowtime, proctime, 所以我們在登錄檔結構的時候額外新增rowtime,proctime。

當需要用到rowtime的使用需要額外指定DataStream.watermarks(assignTimestampsAndWatermarks), 自定義watermark主要做兩個事情:1:如何從Row中獲取時間欄位。 2:設定最大延遲時間。

2、 如何將建立的輸出表sql語句轉換為flink的operator

Flink輸出Operator的基類是OutputFormat, 我們這裡繼承的是RichOutputFormat, 該抽象類繼承OutputFormat,額外實現了獲取執行環境的方法getRuntimeContext(), 方便於我們之後自定義metric等操作。

我們以輸出到mysql外掛mysql-sink為例,分兩部分:

  • 將create table 解析出表名稱,欄位資訊,mysql連線資訊。

該部分使用正規表示式的方式將create table 語句轉換為內部的一個實現類。該類儲存了表名稱,欄位資訊,外掛型別,外掛連線資訊。

  • 繼承RichOutputFormat將資料寫到對應的外部資料來源。

主要是實現writeRecord方法,在mysql外掛中其實就是呼叫jdbc 實現插入或者更新方法。

3、如何將自定義函式語句轉換為flink的operator;

Flink對udf提供兩種型別的實現方式:

1)繼承ScalarFunction

2)繼承TableFunction

需要做的將使用者提供的jar新增到URLClassLoader, 並載入指定的class (實現上述介面的類路徑),然後呼叫TableEnvironment.registerFunction(funcName, udfFunc);即完成了udf的註冊。之後即可使用改定義的udf;

4、維表功能是如何實現的?

流計算中一個常見的需求就是為資料流補齊欄位。因為資料採集端採集到的資料往往比較有限,在做資料分析之前,就要先將所需的維度資訊補全,但是當前flink並未提供join外部資料來源的SQL功能。

實現該功能需要注意的幾個問題:

1)維表的資料是不斷變化的

在實現的時候需要支援定時更新記憶體中的快取的外部資料來源,比如使用LRU等策略。

2)IO吞吐問題

如果每接收到一條資料就序列到外部資料來源去獲取對應的關聯記錄的話,網路延遲將會是系統最大的瓶頸。這裡我們選擇阿里貢獻給flink社群的運算元RichAsyncFunction。該運算元使用非同步的方式從外部資料來源獲取資料,大大減少了花費在網路請求上的時間。

3)如何將sql 中包含的維表解析到flink operator

為了從sql中解析出指定的維表和過濾條件, 使用正則明顯不是一個合適的辦法。需要匹配各種可能性。將是一個無窮無盡的過程。檢視flink本身對sql的解析。它使用了calcite做為sql解析的工作。將sql解析出一個語法樹,透過迭代的方式,搜尋到對應的維表;然後將維表和非維表結構分開。

透過上述步驟可以透過SQL完成常用的從kafka源表,join外部資料來源,寫入到指定的外部目的結構中。


來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/69995740/viewspace-2777221/,如需轉載,請註明出處,否則將追究法律責任。

相關文章