一個作業,多個TTL-Flink SQL 細粒度TTL配置的實現(二)

​(轉自我的微信公衆號 KAMI說 )

在系列文前篇《FlinkSQL細粒度TTL配置的實現(一)》中,我們介紹了實現Flink SQL 細粒度TTL配置的基本原理:通過將原來一段SQL按照TTL的不同拆分爲多段子SQL,然後逐個“翻譯-重註冊”,最終獲得等價於原來一段SQL所描述的但各部分的TTL配置不一樣的DataStream 作業

同時我們也發現,如果中間計算過程包含聚合計算等操作,對應輸出的中間結果爲帶撤回標誌位的數據流(簡稱撤回流)DataStream<Tuple<Boolean, Row>>。Flink 目前無法將撤回流直接註冊爲動態表。

實現所有場景下的 Flink SQL 的細粒度 TTL 配置,關鍵在於解決撤回流注冊爲動態表的問題。

通過閱讀Flink Table API & SQL 的包flink-table的源碼,我們知道:

  1. Flink Table API & SQL 使用 CRow 作爲其內部數據流的基本數據類型,實際上是 Row 類型加上一個標誌位
  2. 每個計算節點的語法邏輯樹節點 RelNode 包含該節點的輸出是否撤回流的屬性produceUpdates,下游節點會根據這個屬性,構造對應的計算邏輯
  3. 數據源註冊到表環境後,對應的 DataStream RelNode 節點爲 DataStreamScan 節點,屬性produceUpdates沒有顯式實現,爲其父類默認值:false,即非撤回流。

通過實現一個簡單的MapFunction,我們可以直接把撤回流轉爲 CRow 數據流,即 DataStream<CRow>

同時,如果對源碼進行一點修改,使得 CRow 數據流時,對應的 DataStreamScan 的屬性 produceUpdates 設置爲 true,那麼就可以實現將撤回流注冊爲動態表這個關鍵特性。具體方法是:

  1. CRow對應的TypeInfomation爲 CRowTypeInfo。表環境的數據流註冊方法的類型檢查以及字段名稱和下標構造的邏輯中,需要添加對CRowTypeInfo 的支持。當輸入 DataStream類型爲 CRowTypeInfo 時,從 CRowTypeInfo 構造 RowTypeInfo,以通過類型檢查以及字段名稱和下標構造:

    // 文件 src/main/scala/org/apache/flink/table/api/TableEnvironment.scala
    /**
    抱歉,因爲這部分代碼已經用於生產環境,爲避免被公司安全掃描認爲是源碼泄漏事故,先臨時移除。
    這部分代碼並不複雜,各位應該可以根據描述實現出來~
    **/
    
  2. RelNode 節點DataStreamScan 已經對就支持 CRow 做了支持,只需要實現屬性produceUpdates。當輸入 DataStream 類型爲 CRowTypeInfo 時,返回True:

    // 文件  src/main/scala/org/apache/flink/table/plan/nodes/datastream/DataStreamScan.scala
    /**
    抱歉,因爲這部分代碼已經用於生產環境,爲避免被公司安全掃描認爲是源碼泄漏事故,先臨時移除。
    這部分代碼並不複雜,各位應該可以根據描述實現出來~
    **/
    

修改完成後,重新編譯源碼,運行下測試,通過了就OK啦。

帶聚合操作的SQL的“翻譯-重註冊”的過程爲:

  1. 通過表環境(即 StreamTableEnvironment)的方法 sqlQuery,將SQL構建爲對應的 Table 對象

  2. 使用表環境的翻譯方法 toRetractStream,將Table對象翻譯爲 DataStream 作業,通過MapFunction將其輸出的撤回流轉換爲 CRow 流

  3. 通過Table 對象的 Schema,構造 CRow 流的數據類型聲明 CRowTypeInfo

  4. 通過表環境的流注冊方法 registerDataStream 將CRow流重新註冊爲動態表。

至此,所有場景下的Flink SQL 細粒度TTL配置的實現完成,希望對大家有幫助~

Tips: 如何判斷Table對象的輸出是撤回流還是非撤回流(即追加流,Append-Only Stream)?我們可以參考源碼做法:

  /**
   * @param tEnv 流表環境
   * @param query 查詢語句對象
   * @return 該查詢是否 Append-Only
   */
  static public boolean isAppendOnly(StreamTableEnvironment tEnv, Table query) {
    return UpdatingPlanChecker.isAppendOnly(tEnv.optimize(query.getRelNode(), false));
  }

PS. 修改源碼不可避免有一定門檻,並且會帶部署上的麻煩,我會嘗試發起Pull Request,將撤回流注冊爲動態表的特性合併到 Flink 以後的版本中。

隨手一讚,支持原創~

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