![](/img/trans.png)
[英]Spring Boot Kafka: Consume same message with all instances for specific topic
[英]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,則所有正在運行的應用程序實例將使用相同的更改日志主題名稱,因此,您打算執行的操作應該是開箱即用的。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.