簡體   English   中英

Kafka Streams - 指向同一主題的所有實例本地商店

[英]Kafka Streams - all instances local store pointing to the same topic

我們有以下問題:

我們想聽某些Kafka主題並構建它的“歷史” - 所以對於指定的密鑰提取一些數據,將其添加到該密鑰的現有列表中(或者如果它不存在則創建一個新的)將它放到另一個主題,它只有一個分區,並且是高度壓縮的。 另一個應用程序可以只聽取該主題並更新它的歷史列表。

我在想它如何適應Kafka流庫。 我們當然可以使用聚合:

msgReceived.map((key, word) -> new KeyValue<>(key, word))
           .groupBy((k,v) -> k, stringSerde, stringSerde)
           .aggregate(String::new,
                     (k, v, stockTransactionCollector) -> stockTransactionCollector + "|" + v,
                     stringSerde, "summaries2")
           .to(stringSerde, stringSerde, "transaction-summary50");

它創建了一個由Kafka支持的本地存儲,並將其用作歷史表。

我擔心的是,如果我們決定擴展這樣的應用程序,每個運行的實例將創建一個新的支持主題${applicationId}-${storeName}-changelog (我假設每個應用程序都有不同的applicationId )。 每個實例開始使用輸入主題,獲取不同的鍵集並構建狀態的不同子集。 如果Kafka決定重新平衡,一些實例將開始錯過本地商店中的一些歷史狀態,因為它們會獲得一組全新的分區。

問題是,如果我只為每個正在運行的實例設置相同的applicationId,它是否應該最終重放來自同一個kafka主題的所有數據,每個運行的實例具有相同的本地狀態?

為什么要創建具有不同ID的多個應用程序來執行相同的工作? Kafka實現並行的方式是通過任務:

應用程序的處理器拓撲通過將其分解為多個任務來擴展。

更具體地說,Kafka Streams基於應用程序的輸入流分區創建固定數量的任務,每個任務分配來自輸入流的分區列表(即Kafka主題)。 分區到任務的分配永遠不會改變,因此每個任務都是應用程序的固定平行單元。

然后,任務可以根據分配的分區實例化自己的處理器拓撲; 它們還為每個分配的分區維護一個緩沖區,並從這些記錄緩沖區一次一個地處理消息。 因此,流任務可以獨立並行地處理,無需人工干預。

如果您需要擴展應用程序,則可以啟動運行相同應用程序的新實例(相同的應用程序ID),並且一些已分配的任務將重新分配給新實例。 本地狀態存儲的遷移將由庫自動處理:

當重新分配發生時,一些分區 - 以及它們相應的任務(包括任何本地狀態存儲) - 將從現有線程“遷移”到新添加的線程。 因此,Kafka Streams在Kafka主題分區的粒度下有效地重新平衡了應用程序實例之間的工作負載。

我建議你看一下本指南

我擔心的是,如果我們決定擴展這樣的應用程序,每個運行的實例將創建一個新的支持主題$ {applicationId} - $ {storeName} -changelog(我假設每個應用程序都有不同的applicationId)。 每個實例開始使用輸入主題,獲取不同的鍵集並構建狀態的不同子集。 如果Kafka決定重新平衡,一些實例將開始錯過本地商店中的一些歷史狀態,因為它們會獲得一組全新的分區。

一些假設不正確:

  • 如果您運行應用程序的多個實例來擴展應用程序,則所有實例都必須具有相同的應用程序ID(參見Kafka的使用者組管理協議) - 否則,將不會共享加載,因為每個實例都將被視為自己的應用程序,並且每個實例都將分配所有分區。

因此,如果所有實例都使用相同的應用程序ID,則所有正在運行的應用程序實例將使用相同的更改日志主題名稱,因此,您打算執行的操作應該是開箱即用的。

暫無
暫無

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

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