Beam 模型基礎

Apache Beam 是一個統一的模型,用於定義批次和串流資料平行處理管道。若要開始使用 Beam,您需要了解一組重要的核心概念

以下章節將更詳細地介紹這些概念,並提供其他文件的連結。

管道

Beam 管道是資料處理工作中所有資料和計算的圖表 (具體而言是有向非循環圖)。這包括讀取輸入資料、轉換該資料,以及寫入輸出資料。管道是由使用者在其選擇的 SDK 中建構。然後,管道會直接透過 SDK 或透過 Runner API 的 RPC 介面前往執行器。例如,此圖表顯示一個分支管道

The pipeline applies two transforms to a single input collection. Eachtransform produces an output collection.

在此圖表中,方塊代表稱為 PTransform 的平行計算,而帶有圓圈的箭頭代表在轉換之間流動的資料 (以 PCollections 的形式)。資料可能是有限的、儲存的資料集,或資料也可能是不斷增長的資料串流。在 Beam 中,大多數轉換同樣適用於有限和無限的資料。

您可以將幾乎任何您能想到的計算表示為圖形作為 Beam 管道。Beam 驅動程式通常會先建立 Pipeline 物件,然後使用該物件作為建立管道的資料集及其轉換的基礎。

如需管道的詳細資訊,請參閱下列頁面

PCollection

PCollection 是一個無序的元素包。每個 PCollection 都是一個可能分散的、同質的資料集或資料串流,並且由建立它的特定 Pipeline 物件擁有。多個管道無法共用 PCollection。Beam 管道會處理 PCollections,而執行器負責儲存這些元素。

PCollection 通常包含「巨量資料」(太多資料而無法在單一機器上的記憶體中存放)。有時,少量資料樣本或中間結果可能會放入單一機器上的記憶體中,但 Beam 的計算模式和轉換著重於需要分散式資料平行計算的情況。因此,無法單獨處理 PCollection 的元素,而是以平行的方式統一處理。

了解 PCollection 的下列特性非常重要。

有限與無限:

PCollection 可以是有限或無限的。

這兩個類別源自於批次處理和串流處理的直覺,但在 Beam 中,這兩者是統一的,有界和無界的 PCollection 可以共存在同一個管道中。如果您的執行器只能支援有界的 PCollection,您必須拒絕包含無界 PCollection 的管道。如果您的執行器僅針對串流,Beam 的支援程式碼中提供了轉接器,將所有內容轉換為針對無界資料的 API。

時間戳記:

PCollection 中的每個元素都有一個相關聯的時間戳記。

當您執行連接到儲存系統的基本連接器時,該連接器負責提供初始時間戳記。執行器必須傳播和聚合時間戳記。如果時間戳記不重要,例如某些元素不表示事件的批次處理作業,則時間戳記將是最小可表示的時間戳記,通常被口語化地稱為「負無限大」。

浮水印:

每個 PCollection 都必須有一個 浮水印,用於估計 PCollection 的完整程度。

浮水印是一種猜測「我們永遠不會看到時間戳記更早的元素」。資料來源負責產生浮水印。執行器必須在處理、合併和分割 PCollection 時實作浮水印傳播。

當浮水印推進到「無限大」時,PCollection 的內容才算完整。透過這種方式,您可以發現無界的 PCollection 是有限的。

視窗化元素:

PCollection 中的每個元素都位於一個 視窗 中。沒有元素會位於多個視窗中;兩個元素除了視窗不同外,可以相等,但它們並非相同。

當元素寫入外部世界時,它們實際上會被放回全域視窗中。寫入資料且不採用此觀點的轉換可能會導致資料遺失。

一個視窗有一個最大時間戳記。當浮水印超過最大時間戳記加上使用者指定的允許延遲時,視窗就會過期。與過期視窗相關的所有資料可能會隨時被捨棄。

編碼器:

每個 PCollection 都有一個編碼器,它是元素二進位格式的規格。

在 Beam 中,使用者的管道可以使用與執行器不同的語言編寫。並非預期執行器可以實際反序列化使用者資料。Beam 模型主要操作編碼資料,「僅是位元組」。每個 PCollection 都有一個宣告的元素編碼,稱為編碼器。編碼器有一個識別編碼的 URN,並且可能有額外的子編碼器。例如,列表的編碼器可能包含列表元素的編碼器。經常使用特定語言的序列化技術,但有一些常見的關鍵格式(例如鍵值對和時間戳記),因此執行器可以理解它們。

視窗化策略:

每個 PCollection 都有一個視窗化策略,它是分組和觸發操作的基本資訊規格。Window 轉換會設定視窗化策略,而 GroupByKey 轉換的行為則受視窗化策略的約束。


有關 PCollection 的更多資訊,請參閱以下頁面

PTransform

PTransform(或轉換)代表管道中的資料處理操作或步驟。轉換通常應用於一個或多個輸入 PCollection 物件。讀取輸入的轉換是例外;這些轉換可能沒有輸入 PCollection

您以函數物件的形式(口語上稱為「使用者程式碼」)提供轉換處理邏輯,並且您的使用者程式碼會應用於輸入 PCollection(或多個 PCollection)的每個元素。根據您選擇的管道執行器和後端,叢集中許多不同的工作者可能會並行執行您的使用者程式碼實例。在每個工作者上執行的使用者程式碼會產生輸出元素,這些輸出元素會加入到零個或多個輸出 PCollection 物件中。

Beam SDK 包含許多不同的轉換,您可以將其應用於管道的 PCollection。這些包括通用核心轉換,例如 ParDoCombine。SDK 中也包含預先寫好的複合轉換,這些轉換會將一個或多個核心轉換組合為有用的處理模式,例如計算或合併集合中的元素。您也可以定義自己的更複雜的複合轉換,以符合您管道的確切使用案例。

以下列表包含一些常見的轉換類型

有關轉換的更多資訊,請參閱以下頁面

聚合

聚合是從多個(1 個或多個)輸入元素計算一個值。在 Beam 中,聚合的主要計算模式是將具有共同鍵和視窗的所有元素分組,然後使用結合律和交換律運算合併每組元素。這類似於 MapReduce 模型中的「Reduce」運算,但它經過增強,可以與無界輸入串流以及有界資料集一起使用。

Aggregation of elements.

圖 1:元素的聚合。具有相同顏色的元素表示具有共同鍵和視窗的元素。

一些簡單的聚合轉換包括 Count(計算聚合中所有元素的計數)、Max(計算聚合中的最大元素)和 Sum(計算聚合中所有元素的總和)。

當元素分組並作為一個包發出時,該聚合稱為 GroupByKey(結合律/交換律運算是包聯集)。在這種情況下,輸出不小於輸入。通常,您將應用一個諸如求和之類的操作,稱為 CombineFn,其中輸出明顯小於輸入。在這種情況下,聚合稱為 CombinePerKey

在實際應用程式中,您可能有數百萬個鍵和/或視窗;這就是為什麼這仍然是一種「可恥地並行」的計算模式。在鍵較少的情況下,您可以透過新增補充鍵來增加並行性,將您問題的每個自然鍵分割成許多子鍵。在這些子鍵聚合後,結果可以進一步合併為您問題的原始自然鍵的結果。聚合函數的結合律可確保這會產生相同的答案,但具有更多的並行性。

當您的輸入是無界時,按鍵和視窗分組元素的計算模式大致相同,但是控制何時以及如何發出聚合結果涉及三個概念

有關可用聚合轉換的更多資訊,請參閱以下頁面

使用者定義函式 (UDF)

某些 Beam 操作允許您執行使用者定義的程式碼,以此來設定轉換。例如,當使用 ParDo 時,使用者定義的程式碼會指定要對每個元素應用的操作。對於 Combine,它會指定應如何合併值。透過使用跨語言轉換,Beam 管道可以包含以不同語言編寫的 UDF,甚至在同一個管道中包含多種語言。

Beam 有幾種不同的 UDF

每個語言 SDK 都有其獨特的方式來表達 Beam 中的使用者定義函數,但有一些共同的要求。當您為 Beam 轉換建立使用者程式碼時,應牢記執行的分散式特性。例如,您的函數可能在許多不同的機器上並行執行多個複本,而這些複本獨立運作,而無需與任何其他複本進行通訊或共享狀態。您的使用者程式碼函數的每個複本可能會重試或多次執行,具體取決於您為管道選擇的管道執行器和處理後端。Beam 還透過有狀態處理 API 支援有狀態處理。

有關使用者定義函數的更多資訊,請參閱以下頁面

綱要

綱要是一種獨立於語言的 PCollection 類型定義。PCollection 的綱要將該 PCollection 的元素定義為已命名欄位的有序列表。每個欄位都有一個名稱、一個類型,並且可能有一組使用者選項。

在許多情況下,PCollection 中的元素類型具有可以內省的結構。一些範例是 JSON、Protocol Buffer、Avro 和資料庫列物件。所有這些格式都可以轉換為 Beam 綱要。即使在 SDK 管道中,簡單的 Java POJO(或其他語言中的等效結構)也經常被用作中間類型,並且它們也具有可透過檢查類別推斷出的明確結構。透過了解管道記錄的結構,我們可以為資料處理提供更簡潔的 API。

Beam 提供了一組在本機上對綱要進行操作的轉換。例如,Beam SQL 是一種對綱要進行操作的常見轉換。這些轉換允許根據已命名的綱要欄位進行選擇和聚合。綱要的另一個優點是它們允許按名稱引用元素欄位。Beam 提供了一種用於引用欄位的選擇語法,包括巢狀和重複欄位。

有關綱要的更多資訊,請參閱以下頁面

執行器

Beam 執行器在特定平台上執行 Beam 管道。大多數執行器都是大量並行大數據處理系統的轉換器或轉接器,例如 Apache Flink、Apache Spark、Google Cloud Dataflow 等等。例如,Flink 執行器會將 Beam 管道轉換為 Flink 作業。Direct Runner 會在本機執行管道,以便您可以測試、偵錯和驗證您的管道是否盡可能符合 Apache Beam 模型。

有關 Beam 執行器的最新列表以及它們支援的 Apache Beam 模型功能,請參閱執行器的功能矩陣

有關執行器的更多資訊,請參閱以下頁面

Window

視窗化會根據個別元素的時間戳記將 PCollection 細分為視窗。視窗透過將集合劃分為有限集合的視窗,來啟用對無界集合的分組操作。

視窗函式會告訴執行器如何將元素指派到一個或多個初始視窗,以及如何合併分組元素的視窗。PCollection 中的每個元素只能存在於一個視窗中,因此如果視窗函式為一個元素指定多個視窗,則該元素在概念上會複製到每個視窗中,並且每個元素除了其視窗之外都是相同的。

彙總多個元素的轉換,例如 GroupByKeyCombine,會隱式地以每個視窗為基礎進行運作;它們會將每個 PCollection 處理為一系列多個、有限的視窗,儘管整個集合本身可能具有無界的大小。

Beam 提供數個視窗函式

如果您有更複雜的需求,您也可以定義自己的視窗函式。

例如,假設我們有一個使用固定時間視窗的 PCollection,其視窗長度為五分鐘。對於每個視窗,Beam 必須收集在給定視窗範圍(例如,第一個視窗中的 0:00 到 4:59 之間)內具有事件時間戳記的所有資料。時間戳記超出該範圍的資料(來自 5:00 或更晚的資料)屬於不同的視窗。

有兩個概念與視窗密切相關,並在以下章節中介紹:水位標記觸發器

有關視窗的詳細資訊,請參閱以下頁面

浮水印

在任何資料處理系統中,資料事件發生的時間(「事件時間」,由資料元素本身的時間戳記決定)與資料元素在管道中的任何階段實際被處理的時間(「處理時間」,由處理元素的系統上的時鐘決定)之間存在一定的延遲。此外,資料不一定保證會依時間順序到達管道,也不一定總是會以可預測的間隔到達。例如,您可能具有不保留順序的中間系統,或者您可能擁有兩個對資料加上時間戳記的伺服器,但其中一個伺服器的網路連線較佳。

為了應對這種潛在的不可預測性,Beam 會追蹤水位標記。水位標記是一種猜測,用於預測特定視窗中的所有資料何時會到達管道。您也可以將其視為「我們永遠不會看到具有更早時間戳記的元素」。

資料來源負責產生水位標記,並且每個 PCollection 都必須具有水位標記,用於估計 PCollection 的完整程度。當水位標記推進到「無限」時,PCollection 的內容即完成。透過這種方式,您可能會發現無界的 PCollection 是有限的。在水位標記通過視窗末端之後,任何後續到達且時間戳記在該視窗中的元素都會被視為延遲資料

觸發器是一個相關的概念,可讓您修改和改進 PCollection 的視窗策略。您可以使用觸發器來決定每個個別視窗何時彙總並報告其結果,包括視窗如何發出延遲元素。

有關水位標記的詳細資訊,請參閱以下頁面

觸發器

當收集資料並將其分組到視窗中時,Beam 會使用觸發器來決定何時發出每個視窗的彙總結果(稱為窗格)。如果您使用 Beam 的預設視窗配置和預設觸發器,當 Beam 估計所有資料都已到達時,它會輸出彙總結果,並捨棄該視窗的所有後續資料。

在高層次上,與在視窗末端輸出相比,觸發器提供了兩個額外的功能

  1. 觸發器可讓 Beam 在給定視窗中的所有資料到達之前發出早期結果。例如,經過一段時間或在一定數量的元素到達之後發出。
  2. 觸發器允許在事件時間水位標記通過視窗末端後透過觸發來處理延遲資料。

這些功能可讓您控制資料流程,並在資料完整性、延遲和成本之間取得平衡。

Beam 提供了許多可以設定的預先建置的觸發器

有關觸發器的詳細資訊,請參閱以下頁面

狀態和計時器

Beam 的視窗和觸發器提供一種抽象,用於根據時間戳記對無界輸入資料進行分組和彙總。但是,某些彙總使用案例可能需要更高程度的控制。狀態和計時器是兩個有助於這些使用案例的重要概念。與其他彙總一樣,狀態和計時器是按每個視窗處理。

狀態:

Beam 提供 State API 用於手動管理每個金鑰的狀態,從而可以對彙總進行細緻的控制。State API 允許您使用可變狀態來擴充元素式操作(例如,ParDoMap)。與其他彙總一樣,狀態是按每個視窗處理。

State API 會對每個金鑰建立狀態模型。若要使用 State API,您需要從鍵控的 PCollection 開始。處理此 PCollectionParDo 可以宣告持續狀態變數。當您在 ParDo 內處理每個元素時,可以使用狀態變數來寫入或更新目前金鑰的狀態,或讀取為該金鑰寫入的先前狀態。狀態始終完全限定於目前的處理金鑰。

Beam 提供數種狀態類型,但不同的執行器可能會支援這些狀態的不同子集。

您可以將 State API 與 Timer API 結合使用,以建立可讓您對工作流程進行細緻控制的處理任務。

計時器:

Beam 提供每個金鑰的計時器回呼 API,可延遲處理使用 State API 儲存的資料。Timer API 允許您設定計時器,以在事件時間或處理時間時間戳記回呼。對於更進階的使用案例,您的計時器回呼可以設定另一個計時器。與其他彙總一樣,計時器是按每個視窗處理。您可以將計時器 API 與 State API 結合使用,以建立可讓您對工作流程進行細緻控制的處理任務。

以下計時器可用

有關狀態和計時器的詳細資訊,請參閱以下頁面

可分割的 DoFn

可分割的 DoFn (SDF) 是 DoFn 的一般化,可讓您以非單體的方式處理元素。可分割的 DoFn 可讓您更輕鬆地在 Beam 中建立複雜的模組化 I/O 連接器。

一般 ParDo 會一次處理整個元素,套用您的一般 DoFn,並等待呼叫終止。當您改為將可分割的 DoFn 套用至每個元素時,執行器可以選擇將元素的處理分割成較小的任務。您可以檢查元素的處理,並分割剩餘的工作以產生額外的平行處理。

例如,假設您想要從非常大的文字檔案中讀取每一行。當您撰寫可分割的 DoFn 時,您可以具有不同的邏輯片段,用於讀取檔案的區段、將檔案的區段分割成子區段,以及報告透過目前區段的進度。然後,執行器可以智慧地叫用您的可分割的 DoFn,以分割每個輸入並平行讀取各部分。

常見的計算模式具有下列步驟

  1. 執行器會在開始任何處理之前分割傳入的元素。
  2. 執行器會開始在每個子元素上執行您的處理邏輯。
  3. 如果執行器注意到某些子元素所花費的時間比其他元素長,執行器會進一步分割這些子元素,並重複步驟 2。
  4. 子元素會完成處理,或者使用者選擇檢查子元素,而執行器會重複步驟 2。

您也可以撰寫可分割的 DoFn,讓執行器可以分割無邊界的處理。例如,如果您撰寫一個可分割的 DoFn 來監看一組目錄,並在檔案抵達時輸出檔案名稱,您可以分割以細分不同目錄的工作。這讓執行器可以分割出熱門目錄並給予額外的資源。

如需更多關於可分割 DoFn 的資訊,請參閱以下頁面

下一步

請參考我們的其他文件,例如 Beam 程式設計指南、管道執行資訊和轉換參考目錄。