大家好,我对TimestampExtractor和Kafka流有疑问。...
在我们的应用程序中,可能会接收到乱序事件,因此我想根据有效内容中的营业日期来排序事件,而不是根据它们放置在主题中的时间点进行排序。
为此,我编写了一个自定义的TimestampExtractor,以便能够从有效负载中提取时间戳。直到我在这里讲的所有内容都运行良好,但是当我针对该主题构建KTable时,我发现接收到乱序的事件(从业务的角度来看,这不是最后一个事件,但最后收到的事件)显示为ConsumerRecord具有来自有效负载的时间戳记,则对象的最后状态。
我不知道假设Kafka Stream将解决TimestampExtractor的此乱序问题可能是我的错误。
然后在调试过程中,我看到如果TimestampExtractor返回-1,因为结果Kafka Streams忽略了消息,并且TimestampExtractor也提供了最后一个接受的事件的时间戳,所以我构建了一个实现以下检查的逻辑(payloadTimestamp 我允许处理这样的逻辑或存在其他方法来处理Kafka流中的乱序事件。... 谢谢。.
答案 0 :(得分:0)
当前(Kafka 2.0)中,KTable
在更新时不考虑时间戳,因为假设是,输入主题中没有乱序数据。进行此假设的原因是“单一作者原则”-假设,对于紧凑的KTable输入主题,每个键只有一个生产者,因此,不会有任何关于数据的乱序数据单键。
这是一个已知问题:https://issues.apache.org/jira/browse/KAFKA-6521
为您解决问题:执行此“ hack”操作并非100%正确或安全:
<key1, value1, 5>, <key2, value2, 3>
的不同消息。与带有时间戳5的第一条记录相比,带有时间戳3的第二条记录要晚一些。但是,两者都有不同的键,因此,您实际上想将第二条记录放入KTable中。仅当您有两个具有相同键的记录时,才希望删除迟到的数据IHMO。TimestampExtractor
会释放第一条记录的时间戳。因此,在重新启动时,它不会丢弃乱序记录。为实现此目的,您将需要在应用程序逻辑中“手动”过滤,而不是无状态且与密钥无关的TimestampExtractor
。无需通过builder#table()
读取数据,您可以将其作为流读取,并应用.groupByKey().reduce()
来构建KTable
。在Reducer
逻辑中,您比较新记录和旧记录的时间戳,并以较大的时间戳返回记录。