我正在使用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)
答案 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
放入消息中。
不允许为分区主题设置其他时间戳提取器,因为必须将上游时间戳转发给下游以确保正确性。