[英]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")
現在,從最初的空狀態開始,一切看起來像這樣:
compacted-topic-1
(empty)
dataKTable
(empty)
// groupBy()
Repartition topic: $APP_ID-age-range-counts-repartition
(empty)
// count()
age-range-counts state store
(empty)
現在,讓我們向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
所以我想知道:
groupBy
並count
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.