简体   繁体   English

有没有办法从Kafka主题获取最新消息?

[英]Is there a way to get the last message from Kafka topic?

I have a Kafka topic with multiple partitions and I wonder if there is a way in Java to fetch the last message for the topic. 我有一个具有多个分区的Kafka主题,我想知道Java中是否有一种方法可以获取该主题的最后一条消息。 I don't care for the partitions I just want to get the latest message. 我不在乎我只想获取最新消息的分区。

I have tried @KafkaListener but it fetches the message only when the topic is updated. 我尝试了@KafkaListener但仅在主题更新时才获取消息。 If there is nothing published after the application is opened nothing is returned. 如果打开应用程序后未发布任何内容,则不会返回任何内容。

Maybe the listener is not the right approach to the problem at all? 也许听众根本不是解决问题的正确方法?

You'll have to consume the latest message from each partition and then do a comparison on the client side (using the timestamp on the message, if it contains it). 您必须使用每个分区中的最新消息,然后在客户端进行比较(如果消息中包含时间戳,则使用消息上的时间戳)。 The reason for this is that Kafka does not guarantee inter-partition ordering. 原因是Kafka不保证分区间排序。 Inside a partition, you can be sure that the message with the largest offset is the latest message pushed to it. 在分区内,可以确保偏移量最大的消息是推送到该消息的最新消息。

This following snippet worked for me. 以下片段对我有用。 You may try this. 您可以尝试一下。 Explanation in the comments. 注释中的解释。

        KafkaConsumer<String, String> consumer = new KafkaConsumer<>(properties);
        consumer.subscribe(Collections.singletonList(topic));

        consumer.poll(Duration.ofSeconds(10));

        consumer.assignment().forEach(System.out::println);

        AtomicLong maxTimestamp = new AtomicLong();
        AtomicReference<ConsumerRecord<String, String>> latestRecord = new AtomicReference<>();

        // get the last offsets for each partition
        consumer.endOffsets(consumer.assignment()).forEach((topicPartition, offset) -> {
            System.out.println("offset: "+offset);

            // seek to the last offset of each partition
            consumer.seek(topicPartition, (offset==0) ? offset:offset - 1);

            // poll to get the last record in each partition
            consumer.poll(Duration.ofSeconds(10)).forEach(record -> {

                // the latest record in the 'topic' is the one with the highest timestamp
                if (record.timestamp() > maxTimestamp.get()) {
                    maxTimestamp.set(record.timestamp());
                    latestRecord.set(record);
                }
            });
        });
        System.out.println(latestRecord.get());

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM