我有一个如下的用例。对于每个传入事件,我想看看 某个字段以查看其状态是否从A更改为B,如果是,请将其发送给 输出主题。流程是这样的:带有键“ xyz”的事件以状态A进入,一段时间后 另一个事件是状态为B的键“ xyz”。我使用高级DSL编写了此代码。
final KStream<String, DomainEvent> inputStream....
final KStream<String, DomainEvent> outputStream = inputStream
.map((k, v) -> new KeyValue<>(v.getId(), v))
.groupByKey(Serialized.with(Serdes.String(), jsonSerde))
.aggregate(DomainStatusMonitor::new,
(k, v, aggregate) -> {
aggregate.updateStatusMonitor(v);
return aggregate;
}, Materialized.with(Serdes.String(), jsonSerde))
.toStream()
.filter((k, v) -> v.isStatusChangedFromAtoB())
.map((k,v) -> new KeyValue<>(k, v.getDomainEvent()));
是否有更好的方法使用DSL编写此逻辑?
有关上面代码中的聚合创建的状态存储的问题的一对。
谢谢!
答案 0 :(得分:8)
默认情况下,将使用持久性RocksDB存储。如果要使用内存存储,则可以传入Materialized.as(Stores.inMemoryKeyValueStore(...))
如果拥有无限数量的唯一键,则最终将耗尽主内存或磁盘,并且应用程序将死亡。根据您的语义,可以通过使用带有大“ gap”参数的会话窗口聚合来获取“ TTL”,而不是使旧密钥过期。
在处理新数据之前,将始终恢复状态。如果您使用内存中存储,这将通过使用基础的changelog主题来实现。根据状态的大小,这可能需要一段时间。如果您使用持久性RocksDB存储,则会从磁盘加载状态,因此无需还原,处理应立即进行。仅在这种情况下,才松开本地磁盘上的状态,才会从changelog主题进行还原。