按密钥对Ktable分组后,时间戳无效(负数)

时间:2019-08-28 08:50:43

标签: apache-kafka apache-kafka-streams

我正在使用KakfkaStreams( 2.3.0 )通过Stream和Ktable(紧凑主题)之间的连接来实现一些价值增值。 问题在于,压缩的主题是使用与流主题不同的分区程序写入的,因此联接无法按预期方式工作(某些键不匹配,因为它们在不同的分区中)。

经纪人版本为0.10.2。

我开始考虑使用 groupBy()再加上 reduce()对压缩的主题进行重新分区,但是当它开始读取创建的重新分区主题时,它将开始抛出 StreamsException 并显示以下消息:

  

输入记录ConsumerRecord(topic = mappings-table-repartition,partition = 18,leaderEpoch = null,offset = 0,CreateTime = -1,serialized key size = 37,serialized value size = 20,headers = RecordHeaders(headers = [],isReadOnly = false),键= 0cecdec3863208e57,值=(11269998780356403403 <-null))具有无效的(负)时间戳。可能是因为使用了0.10之前的生产者客户端将此记录写到Kafka而不嵌入时间戳,或者是因为输入主题是在将Kafka集群升级到0.10+之前创建的。使用其他TimestampExtractor处理该数据。

该分区是由KafkaStreams自动创建并填充的,因此这似乎很奇怪,它将写入无效的记录。 在阅读最初的压缩主题时,我什至尝试提供自定义的时间戳提取器,但没有任何区别。 stacktrace似乎表明它使用的是内部TimestampExtractor(并查看代码确实如此)

  在org.apache.kafka.streams.processor.FailOnInvalidTimestamp.onInvalidTimestamp(FailOnInvalidTimestamp.java:73)中的

      在org.apache.kafka.streams.processor.ExtractRecordMetadataTimestamp.extract(ExtractRecordMetadataTimestamp.java:61)处       在org.apache.kafka.streams.processor.FailOnInvalidTimestamp.extract(FailOnInvalidTimestamp.java:48)       在org.apache.kafka.streams.processor.internals.RecordQueue.updateHead(RecordQueue.java:167)       在org.apache.kafka.streams.processor.internals.RecordQueue.addRawRecords(RecordQueue.java:100)       在org.apache.kafka.streams.processor.internals.PartitionGroup.addRawRecords(PartitionGroup.java:136)       在org.apache.kafka.streams.processor.internals.StreamTask.addRecords(StreamTask.java:746)       在org.apache.kafka.streams.processor.internals.StreamThread.addRecordsToTasks(StreamThread.java:1023)       在org.apache.kafka.streams.processor.internals.StreamThread.runOnce(StreamThread.java:861)       在org.apache.kafka.streams.processor.internals.StreamThread.runLoop(StreamThread.java:805)       在org.apache.kafka.streams.processor.internals.StreamThread.run(StreamThread.java:774)

代码是这样的:

KTable<String, String> table = streamsBuilder
                .table(mappingsTopic,
                       Consumed.with(Serdes.String(), Serdes.String(),
                                      null,
                                      Topology.AutoOffsetReset.EARLIEST))
    .groupBy(KeyValue::pair,
             Grouped.with("mappings-table", Serdes.String(), Serdes.String()))
   .reduce((value1, value2) -> value2, (value1, value2) -> value2)

1 个答案:

答案 0 :(得分:0)

如错误消息所示,您需要升级代理使用的消息格式(请参阅broker config log.message.format.version

从Kafka Streams 1.0开始,需要使用0.10或更高版本的消息格式。

发件人:https://kafka.apache.org/23/documentation/streams/upgrade-guide

  

请注意,经纪人必须使用0.10.1或更高版本才能运行0.10.1或更高版本的Kafka Streams应用程序;磁盘上的消息格式必须为0.10或更高,才能运行1.0或更高版本的Kafka Streams应用程序。对于Kafka Streams 0.10.0,需要经纪人版本0.10.0或更高版本。

Kafka Streams尝试在写入时设置记录时间戳,但是,较旧的消息格式不支持时间戳(在写入时,消息格式降级时,时间戳会丢失)。因此,在读取时,将消息格式转换回时,会将伪时间戳-1放入消息中。

不允许为分区主题设置其他时间戳提取器,因为必须将上游时间戳转发给下游以确保正确性。