我們如何將視窗化功能加入 Apache Flink 批次執行器

我們最近達成了一個重要的里程碑,為 Apache Flink 批次執行器加入了視窗化支援。在這篇文章中,我們想解釋這對 Apache Beam 的使用者意味著什麼,並強調一些實作細節。

不過,在開始之前,讓我們先快速談談 Beam 程式的執行,以及這與今天的文章有何關聯。Beam 管線可以包含有界和無界來源。如果管線僅包含有界來源,則可以以批次方式執行;如果管線包含一些無界來源,則必須以串流方式執行。在 Flink 上執行 Beam 管線時,您不必選擇執行模式。在內部,Flink 執行器會根據管線中是否使用無界來源,將管線轉換為 Flink DataSet 程式或 DataStream 程式。在以下內容中,當我們說「批次執行器」時,我們真正談論的是處於批次執行模式的 Flink 執行器。

這對使用者意味著什麼?

對視窗化的支援是讓 Flink 批次執行器與 Beam 模型相容的最後一塊拼圖。隨著批次執行器的最新變更,使用者現在可以執行任何僅包含有界來源的管線,並確信結果與 Google 作為初始程式碼發布的一部分提供的原始參考實作執行器相符,該程式碼來自 Google Dataflow SDK。

變更最明顯的部分是,現在可以將視窗指派給元素,並且執行器會在 GroupByKeyCombine 操作中尊重這些視窗。一個不太明顯的變更涉及側輸入。在 Beam 模型中,側輸入會尊重視窗;當正在處理主輸入的值時,只有對應於正確視窗的側輸入才能供處理函數(DoFn)使用。

讓側輸入語意正確是自身的一個重要里程碑,因為它允許使用大量的單元測試來驗證執行器實作的正確性。這些測試會演練 Beam 程式模型的所有模糊細節,並驗證執行器產生的結果與您對正確實作的期望相符。在套件中,側輸入用於將預期結果與實際結果進行比較。隨著這些測試的定期執行,我們現在可以更加確信實作會為使用者指定的管線產生正確的結果。

幕後

變更的基礎是在產生的 Flink 轉換中引入 WindowedValue。之前,Beam PCollection<T> 會轉換為 DataSet<T>。現在,我們改為建立 DataSet<WindowedValue<T>>WindowedValue<T> 儲存關於值的元資料,例如時間戳記和指派給它的視窗。

在完成這個基本變更之後,我們只需要確保側輸入尊重視窗,並且 CombineGroupByKey 正確處理視窗。其中棘手的部分是處理合併視窗,例如階段視窗。對於這些視窗,我們基本上是在自己的程式碼中模擬合併 WindowFn 的行為。

在我們讓側輸入正常運作後,我們可以啟用上述測試套件,以檢查執行器在 Beam 模型方面的行為表現如何。正如可以預期的那樣,存在相當多的差異,但我們設法解決了所有問題。在此過程中,我們也簡化了執行器實作。例如,我們移除了所有來源和接收器的自訂轉換,現在僅依賴 Beam 程式碼來執行這些轉換,從而大大減少了維護負擔。

總結

我們在為 Flink 批次執行器加入視窗化支援方面取得了重大進展,從而使其與 Beam 模型相容。由於現在可以在執行器上執行大量的測試套件,我們也對實作的正確性以及未來保持這種狀態感到有信心。