我可以根据给定的分区ID和offset#列表使用kafka消息吗?

时间:2019-12-17 04:24:35

标签: java apache-kafka

鉴于我有一个带有4个分区的kafka主题,每个分区中都有一些已提交的消息。出于某种原因,我想基于给定的分区ID和offset#重播一些已提交的消息,使用Java客户端lib的最佳方法是什么?

例如我有

主题A:

分区1:... offset-1,offset-3,offset-7 ...

分区2:... offset-2,offset-4,offset-8 ...

分区3:...偏移量5,偏移量6,偏移量9 ...

分区4:...偏移量10,偏移量11,偏移量12 ...

我只想重播

分区1:偏移量3

Partition2:偏移量8

Partition3:偏移量5

所以我有如下的伪代码

props.put("max.poll.records", "1"); // to make sure I only get exactly one desired message on that offset 

({(1,3),(2,8),(3,5)}).stream(part_offset-> {
  int i=1; // used as loop count down latch
while(i>=0){
 consumer.assign(get_partition(part_offset.part));
 consumer.seek(new TopicPartition("TopicA", part_offset.part), part_offset.offset);
 records=consumer.pool(Duration.ofSeconds(1)); // I read somewhere kafka is lazy , so should I poll before this ?
 for ( record : records) {
  //do something
  i--;
 }

}

})

但是上面的代码不起作用,它只是挂在那儿什么也不做。 只是想知道用给定的分区ID和偏移信息重播某些消息的最佳方法是什么?还是我以错误的方式消费?请指教

非常感谢

1 个答案:

答案 0 :(得分:0)

对不起,我不好。轮询时,我没有为任何现有的偏移量都没有塞子。所以在限制重试次数之后,下面的代码可以正常工作,请随时发表评论。但是,只是想知道使用int停止此类重试是否是最佳实践吗?谢谢

        props.put("enable.auto.commit", "false");
        props.put("max.poll.records", "1");
        props.put("key.deserializer","org.apache.kafka.common.serialization.StringDeserializer");
        props.put("value.deserializer","org.apache.kafka.common.serialization.StringDeserializer");
        props.put(ConsumerConfig.GROUP_ID_CONFIG, "appname-message-patching");

        List<Pair<Integer,Integer>> partition_offset= Arrays.asList(Pair.of(0,1),Pair.of(0,21),
                Pair.of(1,31) );

        KafkaConsumer<String, String> consumer = new KafkaConsumer<String, String>(props);

        partition_offset.forEach(po-> {
            TopicPartition tp=new TopicPartition(topicName, po.getKey());
            consumer.assign(Arrays.asList(tp));
            consumer.seek(tp,po.getValue());
            int counter=1;//only get 1 message , double guards for max.poll.records ?
            int retry=5;//retry 5 times then give up if cannot receive anything
            while (counter>0 ) {
                ConsumerRecords<String, String> records = consumer.poll(Duration.ofSeconds(1));

                if(retry>0 || !records.isEmpty()) {
                    for (ConsumerRecord<String, String> record : records) {
                        counter--;
                        System.out.printf("==================thread name = %s , partation = %d , offset = %d , key = %s , value = %s\n", Thread.currentThread().getName(), record.partition(), record.offset(), record.key(), record.value());
                    }
                    retry--;
                }
                if (retry==0||counter==0){
                    counter=0;break;
                }
            }
        });
        consumer.close();