我的问题是关于Kafka流Ktable.groupBy.aggregate。以及所得的合计值。
我正在尝试每天汇总分钟事件。
我有一个分钟事件生成器(此处未显示),可以为一些房屋生成事件。有时,事件值不正确,因此必须重新发布分钟事件。 分钟事件在“分钟”主题中发布。 。
我正在使用kafka流groupBy
和aggregate
进行每天和每天这些事件的汇总。
通常一天中只有1440分钟,因此聚合值绝不能超过1440。 而且,永远都不会出现事件数量为负的聚合。
...但是还是会发生,我们不了解代码中的错误。
这里是一个示例简化代码来说明该问题。有时会抛出IllegalStateException。
StreamsBuilder builder = new StreamsBuilder();
KTable<String, MinuteEvent> minuteEvents = builder.table(
"minutes",
Consumed.with(Serdes.String(), minuteEventSerdes),
Materialized.<String, MinuteEvent, KeyValueStore<Bytes, byte[]>>with(Serdes.String(), minuteEventSerdes)
.withCachingDisabled());
// preform daily aggregation
KStream<String, MinuteAggregate> dayEvents = minuteEvents
// group by house and day
.filter((key, minuteEvent) -> minuteEvent != null && StringUtils.isNotBlank(minuteEvent.house))
.groupBy((key, minuteEvent) -> KeyValue.pair(
minuteEvent.house + "##" + minuteEvent.instant.atZone(ZoneId.of("Europe/Paris")).truncatedTo(ChronoUnit.DAYS), minuteEvent),
Grouped.<String, MinuteEvent>as("minuteEventsPerHouse")
.withKeySerde(Serdes.String())
.withValueSerde(minuteEventSerdes))
.aggregate(
MinuteAggregate::new,
(String key, MinuteEvent value, MinuteAggregate aggregate) -> aggregate.addLine(key, value),
(String key, MinuteEvent value, MinuteAggregate aggregate) -> aggregate.removeLine(key, value),
Materialized
.<String, MinuteAggregate, KeyValueStore<Bytes, byte[]>>as(BILLLINEMINUTEAGG_STORE)
.withKeySerde(Serdes.String())
.withValueSerde(minuteAggSerdes)
.withLoggingEnabled(new HashMap<>())) // keep this aggregate state forever
.toStream();
// check daily aggregation
dayEvents.filter((key, value) -> {
if (value.nbValues < 0) {
throw new IllegalStateException("got an aggregate with a negative number of values " + value.nbValues);
}
if (value.nbValues > 1440) {
throw new IllegalStateException("got an aggregate with too many values " + value.nbValues);
}
return true;
}).to("days", minuteAggSerdes);
这是此代码段中使用的示例类:
public class MinuteEvent {
public final String house;
public final double sensorValue;
public final Instant instant;
public MinuteEvent(String house,double sensorValue, Instant instant) {
this.house = house;
this.sensorValue = sensorValue;
this.instant = instant;
}
}
public class MinuteAggregate {
public int nbValues = 0;
public double totalSensorValue = 0.;
public String house = "";
public MinuteAggregate addLine(String key, MinuteEvent value) {
this.nbValues = this.nbValues + 1;
this.totalSensorValue = this.totalSensorValue + value.sensorValue;
this.house = value.house;
return this;
}
public MinuteAggregate removeLine(String key, MinuteEvent value) {
this.nbValues = this.nbValues -1;
this.totalSensorValue = this.totalSensorValue - value.sensorValue;
return this;
}
public MinuteAggregate() {
}
}
如果有人可以告诉我们我们在这里做错了什么,为什么我们会有这些意想不到的价值,那就太好了。
properties.put(StreamsConfig.NUM_STREAM_THREADS_CONFIG, 4);
Ktable.groupBy().aggregate()
,因为分钟值可以是
使用不同的sensorValue
重新发布,用于已发布的Instant。并且每日汇总也相应进行了修改。
Stream.groupBy().aggregate()
没有adder
和substractor
。答案 0 :(得分:0)
我认为,计数实际上可能是负的临时值。
原因是,您的第一个KTable
中的每次更新都会向下游发送 two 消息-下游聚合中要减去的旧值,以及要向其中添加的新值下游聚合。两条消息将在下游聚合中独立处理。
如果当前计数为零,并且在加法之前进行了减法运算,则计数将暂时变为负数。