簡體   English   中英

全局狀態存儲不創建更改日志主題如果全局存儲的輸入主題具有空鍵,有什么解決方法?

[英]global state store don't create change-log topic what is the workaround if input topic to global store has null key?

我讀了很多關於全局狀態存儲的信息,它不會為還原創建更改主題主題,而是使用源主題作為還原。

我正在創建自定義密鑰並將數據存儲在全局狀態存儲中,但在重新啟動后它將消失,因為還原時的全局存儲將直接從源主題獲取數據並繞過處理器。

我的輸入主題有以上數據。

{
      "id": "user-12345",
      "user_client": [
        "clientid-1",
        "clientid-2"
      ]
} 

我正在維護兩個狀態存儲如下:

  1. id ->record(記錄的意思是在json之上)
  2. clientid-1: ["user-12345"] (clientid -> user-id)
  3. clientid-2: ["user-12345"] (clientid -> user-id)

所以我看到的解決方法是創建一個自定義更改日志主題並發送帶有該主題的密鑰的數據,該主題將作為全局狀態存儲的源主題。

但在我的場景中,我必須在狀態存儲中填寫兩條記錄,最好的方法是什么。

示例場景:

Record1: {
          "id": "user-1",
          "user_client": [
            "clientid-1",
            "clientid-2"
          ]
    } 



 Record2:{
          "id": "user-2",
          "user_client": [
            "clientid-1",
            "clientid-3"
          ]
    } 

全局狀態存儲應該具有:

id -> json Record'

clientid-1: ["user-1", "user-2"]
clientid-2: ["user-2"]
clientid-3: ["user-2"]

如何在全局狀態存儲中維護上述場景的恢復情況

一種方法是我們為 GlobalKTable 維護一個變更日志主題(具有保留.policy=compact),我們稱之為user_client_global_ktable_changelog ,為了簡單起見,假設我們將您的消息序列化為 java 類(您可以只使用 HashMap 或 JsonNode 或其他東西) :

//initial message format
public class UserClients {
    String id;
    Set<String> userClient;
}
//message when key is client
public class ClientUsers {
    String clientId;
    Set<String> userIds;
}
//your initial topic
KStream<String, UserClients> userClientKStream = streamsBuilder.stream("un_keyed_topic");
  1. 很容易將記錄重新加密到 user_id,只需重新加密 KStream 然后將其發送到輸出主題
//re-map initial message to user_id:{inital_message_payload}
userClientKStream
        .map((defaultNullKey, userClients) -> KeyValue.pair(userClients.getId(), userClients))
        .to("user_client_global_ktable_changelog");//please provide appropriate serdes
  1. 聚合特定客戶端的 user_id,我們可以使用本地狀態(KTable)來保存(當前 client_id 的當前 user_ids 列表):
userClientKStream
        //will cause data re-partition before running groupByKey (will create an internal -repartition topic)
        .flatMap((defaultNullKey, userClients)
                -> userClients.getUserClient().stream().map(clientId -> KeyValue.pair(clientId, userClients.getId())).collect(Collectors.toList()))
        //we have to maintain a current aggregated store for user_ids for a particular client_id
        .groupByKey()
        .aggregate(ClientUsers::new, (clientId, userId, clientUsers) -> {
            clientUsers.getUserIds().add(userId);
            return clientUsers;
        }, Materialized.as("client_with_aggregated_user_ids"))
        .toStream()
        .to("user_client_global_ktable_changelog");//please provide appropriate serdes

例如,在本地狀態下聚合 user_ids:

//re-key message for client-based message
clientid-1:user-1
//your current aggregated for `clientid-1`
"clientid-1"
{
    "user_id": ["user-1"]
}

//re-key message for client-based message
clientid-1:user-2
//your current aggregated for `clientid-1`
"clientid-1"
{
    "user_id": ["user-1", "user-2"]
}

實際上,如果您進行一些更改,我們可以直接使用本地狀態的更改日志主題作為your_application-client_with_aggregated_user_ids-changelog ,即主題your_application-client_with_aggregated_user_ids-changelog ,通過調整狀態以保留用戶密鑰和客戶端密鑰消息的有效負載。

暫無
暫無

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

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