我有一个KStream
管道,该管道按键分组,然后按一定的时间间隔对窗口进行分组,然后在该管道上应用自定义聚合:
KStream<String, Integer> input = /* define input stream */
/* group by key and then apply windowing */
KTable<Windowed<String>, MyAggregate> aggregateTable =
input.groupByKey()
.windowedBy(/* window defintion here */)
.aggregate(MyAggregate::new, (key, value, agg) -> agg.addAndReturn(value))
// I need to get a change log of aggregateTable so:
aggregateTable.toStream().to("output-topic");
问题在于大多数输入记录不会更改MyAggregate
对象的内部状态。结构类似于:
class MyAggregate {
private Set<Integer> checkBeforeInsert = /* some predefined values */
private List<Integer> actualState = new ArrayList<>();
public MyAggregate addAndReturn(Integer value) {
/* for 99% of records the if check passes */
if (checkBeforeInsert.contains(value)) {
/* do nothing and return. Note that the state hasn't been changed */
return this;
} else {
actualState.add(value);
return this;
}
}
}
但是,KStream
没有任何线索表明聚合对象尚未更改,它仍然存储聚合(与旧的相同)。它还将传播到相同的旧值以更改日志主题,并使用相同的旧值触发aggregateTable.toStream()
。
尽管我的应用程序的语义正常(其他应用程序意识到未更改状态可能会到达这一事实),但这会在中间主题上产生巨大的噪音。我需要一种方法来通知KStream
汇总是否确实已更改并且应该存储或与先前的记录相同(只是忽略它)。