簡體   English   中英

這種聚合在 Kafka 流中是如何工作的?

[英]How does this aggregation works in the Kafka stream?

我是 Apache Kafka 的新手。 我閱讀了一個 Steam 應用程序的代碼,偶然發現了聚合操作。 我試圖自己理解它,如果我的解釋正確,我需要確認。

下面提供了從主題和聚合中讀取的代碼片段,

// json Serde
final Serializer<JsonNode> jsonSerializer = new JsonSerializer();
final Deserializer<JsonNode> jsonDeserializer = new JsonDeserializer();
final Serde<JsonNode> jsonSerde = Serdes.serdeFrom(jsonSerializer, jsonDeserializer);


KStreamBuilder builder = new KStreamBuilder();

// read from the topic 'bank-transactions' as `KStream`. I provided the producer below 
KStream<String, JsonNode> bankTransactions = builder.stream(Serdes.String(), jsonSerde, "bank-transactions");

// we define the grouping and aggregation here 
KTable<String, JsonNode> bankBalance = bankTransactions.groupByKey(Serdes.String(), jsonSerde)
    .aggregate(
            () -> initialBalance,
            (key, transaction, balance) -> newBalance(transaction, balance),
            jsonSerde,
            "bank-balance-agg"
    );

bank-transactions主題的數據流產生如下,

public static ProducerRecord<String, String> newRandomTransaction(String name) {
    // creates an empty json {}
    ObjectNode transaction = JsonNodeFactory.instance.objectNode();

    Integer amount = ThreadLocalRandom.current().nextInt(0, 100);

    // Instant.now() is to get the current time using Java 8
    Instant now = Instant.now();

    // we write the data to the json document
    transaction.put("name", name);
    transaction.put("amount", amount);
    transaction.put("time", now.toString());

    return new ProducerRecord<>("bank-transactions", name, transaction.toString());
}

初始余額如下啟動,

// create the initial json object for balances
ObjectNode initialBalance = JsonNodeFactory.instance.objectNode();

initialBalance.put("count", 0);
initialBalance.put("balance", 0);
initialBalance.put("time", Instant.ofEpochMilli(0L).toString());

newBalance方法接受交易和余額並返回新余額,

private static JsonNode newBalance(JsonNode transaction, JsonNode balance) {
    // create a new balance json object
    ObjectNode newBalance = JsonNodeFactory.instance.objectNode();

    newBalance.put("count", balance.get("count").asInt() + 1);
    newBalance.put("balance", balance.get("balance").asInt() + transaction.get("amount").asInt());

    Long balanceEpoch = Instant.parse(balance.get("time").asText()).toEpochMilli();
    Long transactionEpoch = Instant.parse(transaction.get("time").asText()).toEpochMilli();

    Instant newBalanceInstant = Instant.ofEpochMilli(Math.max(balanceEpoch, transactionEpoch));
    newBalance.put("time", newBalanceInstant.toString());

    return newBalance;
}

我有兩個關於分組和聚合的問題,

一種。 groupByKey由分組Serdes.String()jsonSerde只執行對蒸汽數據序列化和反序列化? Serdes.String()newRandomTransaction方法中的名稱字符串。

我的主張是key, transaction里面aggregation了線的功能(key, transaction, balance) -> newBalance(transaction, balance)從讀取bank-transactions的話題和balance從未來initialBalance從上一行。 那是對的嗎?

盡管它無縫運行,但我在嘗試調試該應用程序時也感到困惑。

groupByKey 是否按 Serdes.String() 分組,而 jsonSerde 僅對 Steam 數據執行序列化和反序列化?

是的,groupByKey 是按鍵分組,可以反序列化並作為字符串進行比較

我的斷言是行 (key, transaction, balance) -> newBalance(transaction, balance) 的聚合函數中的關鍵,交易是從銀行交易主題中讀取的,余額來自上一行的 initialBalance

幾乎。 初始化器在第一個參數上,是的,但是聚合的結果在應用程序的整個執行過程中都被結轉,無休止地聚合。

換句話說,您總是從initialBalance開始,然后對於每個相同的鍵,您將該transaction的余額添加到該鍵的當前累積balance中。 如果您還沒有看到重復的密鑰,那么它才會被添加到初始余額中

是的,您的輸入主題是由 KStreams builder.stream方法指定的

暫無
暫無

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

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