如何合并多个 kafka 流以便对结果流的所有事件进行会话窗口化

How to merge multiple kafka streams in order to do a session windowing over all events of the resulting stream

我们有多个具有不同业务事件(页面浏览、点击、滚动事件等)的输入主题。据我了解 Kafka 流,它们都有一个事件时间戳,可用于 KStream 与其他流或表的连接以对齐时间。

我们想要做的是:合并所有不同的事件(源自上述不同主题)的用户 ID(即按用户 ID 分组)并向它们应用会话 window。

这应该可以通过在包含所有事件的流上使用 groupByKey 然后 aggregate/reduce(在此处指定不活动时间)来实现。这个组合流必须按照事件时间的顺序包含来自不同输入主题的所有事件(或者以上述 kafka 流方法遵循此事件时间的方式)。

剩下的唯一挑战就是创建这个组合/合并的流。

当我查看 Kafka Streams API 时,有一个 KStreamBuilder#merge 操作,javadoc 说:There is no ordering guarantee for records from different {@link KStream}s.。这是否意味着会话窗口将产生不正确的结果?

如果是,#merge 的替代方案是什么?

What we want to do is: Merge all different events (originating from the above mentioned different topics) for a user id (i.e. group by user id) and apply a session window to them.

据我了解,您需要 join the streams(并使用 groupBy 以确保它们可以通过用户 ID 正确加入),而不是合并它们。然后您可以跟进会话窗口聚合。

我也在考虑加入,但实际上这似乎取决于您是每个主题每个 ID 有一个事件,还是在一个输入主题中可能有多个具有相同 ID 的事件。对于第一种情况,加入是一个很好的策略,但对于第二种情况则不然,因为你会得到一些不必要的重复。

stream A: <a,1> <a,2>
stream B: <a,3>
join-output plus session: <a,1-3 + 2-3>

编号 3 将重复。

另请记住,加入会稍微修改时间戳,因此如果您将它们应用于联接结果或原始数据,您的会话 windows 可能会有所不同。

关于 merge() 和订购。您可以安全地使用 merge(),因为会话 windows 将基于记录时间戳而非偏移顺序构建。并且 Kafka Streams 中的所有 window 操作都可以优雅地处理乱序数据。