簡體   English   中英

Kafka Streams - 更新KTable上的聚合

[英]Kafka Streams - updating aggregations on KTable

我有一個KTable ,其數據看起來像這樣(key => value),其中key是客戶ID,值是包含一些客戶數據的小JSON對象:

1 => { "name" : "John", "age_group":  "25-30"}
2 => { "name" : "Alice", "age_group": "18-24"}
3 => { "name" : "Susie", "age_group": "18-24" }
4 => { "name" : "Jerry", "age_group": "18-24" }

我想對這個KTable進行一些聚合,並且基本上保留每個age_group的記錄數。 所需的KTable數據如下所示:

"18-24" => 3
"25-30" => 1

讓我們說Alice ,她在上面的18-24組,有一個生日,讓她進入新的年齡組。 支持第一個KTable的狀態存儲現在應該如下所示:

1 => { "name" : "John", "age_group":  "25-30"}
2 => { "name" : "Alice", "age_group": "25-30"} # Happy Cake Day
3 => { "name" : "Susie", "age_group": "18-24" }
4 => { "name" : "Jerry", "age_group": "18-24" }

我希望得到的聚合KTable結果能夠反映出這一點。 例如

"18-24" => 2
"25-30" => 2

可能過度概括了這里描述的問題:

在Kafka Streams中沒有最終聚合......根據您的使用情況,手動重復數據刪除將是解決問題的一種方法“

但到目前為止我只能算出一個跑步總數,例如愛麗絲的生日會被解釋為:

"18-24" => 3 # Old Alice record still gets counted here
"25-30" => 2 # New Alice record gets counted here as well

編輯:這是我注意到的一些額外行為似乎意外。

我正在使用的拓撲看起來像:

dataKTable = builder.table("compacted-topic-1", "users-json")
    .groupBy((key, value) -> KeyValue.pair(getAgeRange(value), key))
    .count("age-range-counts")

1)空狀態

現在,從最初的空狀態開始,一切看起來像這樣:

compacted-topic-1
(empty)


dataKTable
(empty)


// groupBy()
Repartition topic: $APP_ID-age-range-counts-repartition
(empty)

// count()
age-range-counts state store
(empty)

2)發送幾條消息

現在,讓我們向compacted compacted-topic-1發送一條消息,該消息在上面作為KTable流傳輸。 這是發生的事情:

compacted-topic-1
3 => { "name" : "Susie", "age_group": "18-24" }
4 => { "name" : "Jerry", "age_group": "18-24" }

dataKTable
3 => { "name" : "Susie", "age_group": "18-24" }
4 => { "name" : "Jerry", "age_group": "18-24" }


// groupBy()
// why does this generate 4 events???
Repartition topic: $APP_ID-age-range-counts-repartition
18-24 => 3
18-24 => 3
18-24 => 4
18-24 => 4

// count()
age-range-counts state store
18-24 => 0

所以我想知道:

  • 我正在嘗試使用Kafka Streams 0.10.1或0.10.2做什么? 我嘗試過使用groupBycount DSL,但也許我需要使用像reduce這樣的東西?
  • 另外,我在理解導致add reducer和subtract減速器被調用的情況時遇到了一些麻煩,因此任何這些點的任何澄清將不勝感激。

如果你有原始的KTable包含id -> Json數據(讓我們稱之為dataKTable )你應該能夠得到你想要的東西

KTable countKTablePerRange
    = dataKTable.groupBy(/* map your age-range to be the key*/)
                .count("someStoreName");

這適用於所有版本的Kafka Streams API。

更新

關於重新分區主題中的4個值:這是正確的。 對“base KTable ”的每次更新KTable記錄“舊值”並記錄“新值”。 這是正確更新下游KTable所必需的。 必須從一個計數中刪除舊值,並且必須將新值添加到另一個計數中。 由於您的(計數) KTable可能是分布式的(即,在多個並行運行的應用程序實例上共享),因此兩個記錄(舊的和新的)可能最終會出現在不同的實例中,因為它們可能具有不同的密鑰,因此它們必須作為兩個獨立的記錄發送。 (記錄格式應該比你在問題中顯示的更復雜。)

這也解釋了為什么你需要一個減法器和一個加法器。 減法器從agg結果中刪除舊記錄,而加法器將新記錄添加到agg結果中。

仍然不確定為什么你沒有在結果中看到正確的計數。 你運行了多少個實例? 也許嘗試通過在StreamsConfig設置cache.max.bytes.buffering=0來禁用KTable緩存。

暫無
暫無

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

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