簡體   English   中英

自定義無限制來源如何在Google Cloud DataFlow中運行?

[英]How custom unbounded sources work in Google Cloud DataFlow?

我正在嘗試為Google Cloud Dataflow實施自定義無限制來源,以便從Amazon Kinesis隊列中讀取。 為了正確實現檢查點,我想了解該機制是如何工作的。

DataFlow如何工作

我試圖通過閱讀DataFlow的文檔來了解檢查點,但是缺少一些關鍵的東西,所以我瀏覽了一篇MillWheel論文。 首先讓我解釋一下我是如何理解本文所提出的概念的。 在數據流API方面,我將重點介紹源代碼與其消費者之間在強大的生產設置中的交互:

  • 在源上調用createReader() ,並將null值作為CheckpointMark傳遞
  • 在reader實例上調用start()
  • advance()在讀者上被調用X次
  • 現在工人決定制作一個檢查站標記。 它在閱讀器上調用getCheckpointMark()
  • 檢查點由工人持久化
  • 在檢查點對象上調用finalizeCheckpoint()
  • 到目前為止讀取的數據被發送給消費者,消費者將記錄存儲在高速緩存中以便對可能的重試進行重復數據刪除
  • 消費者向源發送ACK。 此時檢查點從源中刪除,當接受ACK時,消費者從緩存中刪除記錄(因為此時源不會重試)
  • 如果源無法接收ACK,那么它將創建新的讀取器實例,將最后一個檢查點作為參數傳遞,它將重試向消費者發送數據。 如果消費者收到重試數據,它將嘗試進行重復數據刪除
  • 一切都重復了。 它是如何發生的還不清楚:是第一個用於繼續從流中讀取的讀者實例嗎? 或者創建具有空檢查點標記的新閱讀器以執行此操作? 或者是用於繼續從流中讀取的第二個讀取器(帶有檢查點數據)?

PubSub vs. Kinesis

現在,請讓我談談Kinesis隊列如何運作,因為它與Pub / Sub存在顯着差異(因為我了解Pub / Sub的工作方式,我自己並沒有使用它)。

發布/訂閱

我看到Pub / Sub pull模型嚴重依賴於ACK,即客戶端接收的消息被確認,然后Pub / Sub中的“內部檢查點”向前移動 - >這意味着即將到來的pull請求將在前一個ACK之后接收連續記錄。

室壁運動

Kinesis pull界面(根本沒有推送)更類似於你與文件的交互方式。 您可以在流中的任何位置開始讀取(特殊值TRIM_HORIZON是流中最舊的記錄,LATEST是流中的最新記錄)然后使用迭代器按記錄向前移動(迭代器存儲在服務器端並具有5分鍾到期時間,如果未使用)。 服務器沒有ACK - 客戶端負責跟蹤流中的位置,並且您可以隨時重新讀取舊記錄(當然,除非它們已過期)。

問題/問題

  • 檢查點應該如何? 給定檢查點的讀者是否只讀取與其相關的部分數據,或者是否希望從檢查點讀取所有數據? 換句話說,我的檢查點應該是:“x和y之間的數據”或“x之后的所有數據”?
  • 我知道第一個讀取器作為檢查點標記變為空,這非常好 - 這意味着我應該從應用程序開發人員定義的點開始閱讀。 但是,DataFlow可以像這樣創建其他讀取器嗎(例如,我想象讀取器jvm死亡的情況,然后DataFlow使用新讀取器傳遞null作為檢查點創建新的讀取器)? 在這種情況下,我不知道我的起始位置是什么,因為我可能已經使用以前的讀者閱讀了一些數據,現在進度的標記丟失了。
  • 哪個id用於消費者方面的記錄重復數據刪除? 它是由getCurrentRecordId返回的值嗎? 我問這個問題,因為我考慮過使用流中的位置,因為它對於特定的流是唯一的。 但是,如果我稍后通過展平它們加入一些kinesis來源會發生什么 - >這會導致不同記錄可能共享相同ID的情況。 我應該使用(流名稱,位置)元組作為id(在這種情況下是唯一的)。

干杯,普熱梅克

我們很高興看到您將數據流與Kinesis一起使用。 我們希望通過Kinesiscontrib連接器向我們的GitHub項目提出拉取請求。 我們也很樂意在您開發時通過GitHub審核您的代碼並在那里給您反饋。

檢查點應該如何? 給定檢查點的讀者是否只讀取與其相關的部分數據,或者是否希望從檢查點讀取所有數據? 換句話說,我的檢查點應該是:“x和y之間的數據”或“x之后的所有數據”?

檢查點標記應代表“由此讀者生成並最終確定的數據”。 例如,如果讀者負責特定分片,則檢查點標記可能包含分片標識符和該分片中已成功讀取的最后序列號Y,表示“已生成所有數據,包括Y”。

我知道第一個讀取器作為檢查點標記變為空,這非常好 - 這意味着我應該從應用程序開發人員定義的點開始閱讀。 但是,DataFlow可以像這樣創建其他讀取器嗎(例如,我想象讀取器jvm死亡的情況,然后DataFlow使用新讀取器傳遞null作為檢查點創建新的讀取器)? 在這種情況下,我不知道我的起始位置是什么,因為我可能已經使用以前的讀者閱讀了一些數據,現在進度的標記丟失了。

即使在JVM失敗的情況下,也會持久化最終檢查點。 換句話說,當JVM死亡時,讀者將使用最終確定的最后一個檢查點構建。 您不應該看到使用空檢查點創建的讀者,除非它們打算從源的開頭讀取,或者在JVM在第一次成功調用finalizeCheckpoint()之前死亡的情況下讀取。 您可以使用新讀取器上的檢查點標記為從要讀取的下一條記錄開始的相同分片構造新的迭代器,並且可以繼續而不會丟失數據。

哪個id用於消費者方面的記錄重復數據刪除? 它是由getCurrentRecordId返回的值嗎? 我問這個問題,因為我考慮過使用流中的位置,因為它對於特定的流是唯一的。 但是,如果我稍后通過展平它們加入一些kinesis來源會發生什么 - >這會導致不同記錄可能共享相同ID的情況。 我應該使用(流名稱,位置)元組作為id(在這種情況下是唯一的)。

在數據流,每個UnboundedSource(實現getCurrentRecordId和覆蓋requiresDeduping返回true )是去欺騙自身。 因此,記錄ID僅對同一源實例是唯一的。 來自兩個不同來源的記錄可以使用相同的記錄ID,並且在展平期間不會將它們視為“重復”。 因此,如果Amazon Kinesis保證所有記錄都具有全局唯一的ID(跨流中的所有分片)和持久性(例如,在重新分片操作中),那么這些ID應該適合用作記錄ID。

請注意, getCurrentRecordIdUnboundedReader可選方法 - 如果檢查點方案唯一標識每條記錄,則無需實現它。 Kinesis允許您按序列號順序讀取記錄,看起來序列號是全局唯一的。 因此,您可以將每個分片分配給generateInitialSplits的不同工作程序,並且每個工作程序可能不會生成重復數據 - 在這種情況下,您可能根本不需要擔心記錄ID。

大多數答案都假設了一個簡單的例子,你的Kinesis流不會改變它們的分片。 另一方面,如果流上的分片發生變化,那么您的解決方案將變得更加復雜。 例如,每個工人可能負責超過1個碎片,因此檢查點標記將是碎片 - >序列號而不是序列號的映射。 拆分和合並的分片可以在不同的數據流工作者之間移動以平衡負載,並且可能很難保證兩個不同的工作人員不會讀取兩次Kinesis記錄。 在這種情況下,使用帶有您描述的語義的Kinesis記錄ID就足夠了。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM