Java Kafka流聚合:如何忽略窗口的中间聚合结果
我们使用带有时间窗口的Java Kafka流聚合:如何忽略窗口的中间聚合结果,java,apache-kafka-streams,Java,Apache Kafka Streams,我们使用带有时间窗口的kafka流聚合来计算事件的结束和。我们已经实现了我们的需求,但中间聚合结果存在问题。根据卡夫卡内存管理文档(),似乎没有办法放弃这些影响最终结果的中间结果。请考虑下面的解释,从上面的文件中获取。 使用以下示例了解有无行为 记录缓存。在本例中,输入是一个KStream,带有记录:,。 本例中的重点是key==A的记录 聚合计算按键分组的记录值的总和 输入并返回一个KTable 无缓存:为键a发出一系列输出记录 表示结果聚合表中的更改的。这个 括号(())表示更改,左边的数字
kafka流
聚合来计算事件的结束和。我们已经实现了我们的需求,但中间聚合结果存在问题。根据卡夫卡内存管理文档(),似乎没有办法放弃这些影响最终结果的中间结果。请考虑下面的解释,从上面的文件中获取。
使用以下示例了解有无行为
记录缓存。在本例中,输入是一个KStream
,带有记录:,
。
本例中的重点是key==A
的记录
聚合计算按键分组的记录值的总和
输入并返回一个KTable
无缓存:为键a发出一系列输出记录
表示结果聚合表中的更改的。这个
括号(())表示更改,左边的数字是新的聚合
值,正确的数字是旧的聚合值:
,
使用缓存:为键a发出一条输出记录,该记录将
很可能在缓存中被压缩,导致
。此记录将写入聚合的
内部状态存储并转发给任何下游操作
缓存大小通过cache.max.bytes.buffering指定
参数,它是每个处理拓扑的全局设置:
根据文档,在不缓存输出记录的情况下使用聚合时会产生增量结果。(我们注意到,即使使用缓存,有时也会发生这种情况)。我们的问题是,我们还有其他应用程序对这些输出聚合进行操作,并进行一些计算。因此,当输出具有中间聚合时,这些其他计算出错。例如,当我们有
事件时,我们可能会开始计算其他内容(应该在
该时间窗口上进行正确的计算)
我们的要求是只对该窗口上的最终聚合进行其他计算
<> LI>当KAKFA输出中间结果时,这些输出不是已经聚合数据吗?例如,考虑输出<代码>,<代码>。第二个输出事件在这里<代码> <代码>,第三个输出<代码> /代码>已经聚合值。这是正确的吗?
有没有办法确定窗口的中间结果
另一件需要记住的事情是提交时间间隔和缓存大小控制结果向下游转发的时间
例如,如果提交间隔为10秒,则意味着缓存中的结果将被转发(如果启用了日志记录,则将其写入changelog主题),而不管缓存是否已满
<> p>因此,如果您可以将内存设置得足够高,以支持将提交间隔设置为所需的窗口时间,则可以近似一个最终结果。当然,这是一种粗粒度的方法,并影响整个拓扑结构,因此您需要考虑并可能原型应用程序以查看该方法是否可行。对于您。另一件需要记住的事情是提交时间间隔,缓存大小决定结果向下游转发的时间
例如,如果提交间隔为10秒,则意味着缓存中的结果将被转发(如果启用了日志记录,则将其写入changelog主题),而不管缓存是否已满
<> p>因此,如果您可以将内存设置得足够高,以支持将提交间隔设置为所需的窗口时间,则可以近似一个最终结果。当然,这是一种粗粒度的方法,并影响整个拓扑结构,因此您需要考虑并可能原型应用程序以查看该方法是否可行。为您。我想您所寻求的是窗口的最终结果。因此,您可以抑制结果,以便只发布最终结果
以下是抑制最终结果的示例:
KGroupedStream<UserId, Event> grouped = ...;
grouped
.windowedBy(TimeWindows.of(Duration.ofHours(1)).grace(ofMinutes(10)))
.count()
.suppress(Suppressed.untilWindowCloses(unbounded()))
.filter((windowedUserId, count) -> count < 3)
.toStream()
.foreach((windowedUserId, count) -> sendAlert(windowedUserId.window(), windowedUserId.key(), count));
KGroupedStream group=。。。;
分组
.windowedBy(时间窗的持续时间(1)).grace(分钟的持续时间(10)))
.count()
.suppress(supprested.untilwindowclose(unbounded()))
.filter((windowedUserId,计数)->计数<3)
.toStream()
.foreach((windowedUserId,count)->sendAlert(windowedUserId.window(),windowedUserId.key(),count));
正如您所看到的suppress(Suppressed.untilwindowclose(unbounded())
起到了作用。我想您要寻找的是窗口的最终结果。因此,您可以抑制结果,以便只发布最终结果
以下是抑制最终结果的示例:
KGroupedStream<UserId, Event> grouped = ...;
grouped
.windowedBy(TimeWindows.of(Duration.ofHours(1)).grace(ofMinutes(10)))
.count()
.suppress(Suppressed.untilWindowCloses(unbounded()))
.filter((windowedUserId, count) -> count < 3)
.toStream()
.foreach((windowedUserId, count) -> sendAlert(windowedUserId.window(), windowedUserId.key(), count));
KGroupedStream group=。。。;
分组
.windowedBy(时间窗的持续时间(1)).grace(分钟的持续时间(10)))
.count()
.suppress(supprested.untilwindowclose(unbounded()))
.filter((windowedUserId,计数)->计数<3)
.toStream()
.foreach((windowedUserId,count)->sendAlert(windowedUserId.window(),windowedUserId.key(),count));
正如您所看到的suppress(Suppressed.untilwindowcloss(unbounded())
起到了作用。我认为这里可以使用示例,唯一的问题是复制密钥,我需要获取最后一个条目(不是示例中所示的第一个条目)。我也尝试了这一点,但似乎不太容易(容易出错)您需要手动构建一个具有状态存储和“重复数据消除”中间结果的自定义处理器。我还想指出,KIP-328建议将“最终结果”功能添加到Kafka Streams中:我认为这里可以使用示例,唯一的问题是我需要使用的重复密钥