如何从kafka流中获取最新价值

时间:2019-12-18 15:55:57

标签: scala apache-kafka streaming kafka-consumer-api

我对Kafka和流媒体还不是很陌生。我有一个要求,比如每次运行kafka生产者和消费者时,我都应该获得生产者产生的唯一消息。

下面是生产者和消费者的基本代码

制作人

 val props = new Properties()
    props.put("bootstrap.servers", "localhost:9092")
    props.put("key.serializer", "org.apache.kafka.common.serialization.StringSerializer")
    props.put("value.serializer", "org.apache.kafka.common.serialization.StringSerializer")
    val producer = new KafkaProducer[String, String](props)
    val record = new ProducerRecord[String, String]("test", "key", jsonstring)
    producer.send(record)
    producer.close()

消费者

val props = new Properties()
    props.put("bootstrap.servers", "localhost:9092")
    props.put("key.deserializer", "org.apache.kafka.common.serialization.StringDeserializer")
    props.put("value.deserializer", "org.apache.kafka.common.serialization.StringDeserializer")
    props.put("auto.offset.reset", "earliest")
    props.put("group.id", "13")
    val consumer: KafkaConsumer[String, Map[String,Any]] = new KafkaConsumer[String, Map[String,Any]](props)
    consumer.subscribe(util.Arrays.asList("test"))
    while (true) {
      val record = consumer.poll(1000).asScala
      for (data <- record.iterator){
        println(data.value())

      }

我正在使用的输入Json是以下

{

“ id”:1,

“名称”:“ foo”

}

现在我面临的问题是每次运行程序时我都会得到重复的值。例如,如果我两次运行代码,则消费者输出看起来像这样

{

“ id”:1,

“名称”:“ foo”

}

{

“ id”:1,

“名称”:“ foo”

}

我想要输出,就像我运行程序一样,生产者处理的唯一消息应该被消耗并打印。

我尝试了一些操作,例如将消费者属性更改为偏移量为最新

props.put("auto.offset.reset", "latest")

我也尝试了以下提到的方法,但对我没有用 How can I get the LATEST offset of a kafka topic?

请问您有其他建议吗?

1 个答案:

答案 0 :(得分:2)

消费者从主题分区按顺序读取消息。 如果调用poll(),它将返回写入Kafka的记录,而我们组中的消费者尚未读取这些记录。 Kafka在每个分区上跟踪其消耗偏移量,以了解在重新启动的情况下从何处开始消耗。 消费者通过使用提交在主题__consumer_offsets中维护其分区偏移量。

  

提交是在中更新当前位置的操作   __consumer_offsets。

如果使用者重新启动,为了知道从哪里开始使用,使用者将读取每个分区的最新提交的偏移量,然后从那里继续。

您可以通过两种方式控制提交,或者使用提交间隔将auto commit设置为true

1。启用。auto.committrue

props.put("enable.auto.commit", "true");
props.put("auto.commit.interval.ms", "1000");

2。手动提交

consumer.commitAsync();//asyn commit
or  
consumer.commitSync();//sync commit

如果提交失败,它将从最后提交的位置重新开始,如下图所示

enter image description here

自动偏移重置:

消费者第一次重启后,会使用 auto.offset.reset 来确定每个分配分区的初始位置。请注意,首次使用唯一的组ID创建组时,在使用任何消息之前,位置均根据可配置的偏移重置策略 (auto.offset.reset) 进行设置。之后,它将继续逐渐消耗消息,并使用commit(如上所述)跟踪最新的消耗消息

  

注意:在如果使用者在提交任何偏移量之前崩溃,   那么接管其分区的使用者将使用重置   政策。

所以就您而言

  1. 对于手动提交,请使用手动偏移提交或enable.auto.commit true。
  2. 如果更改组将对待不同的使用者并使用auto.offset.reset分配偏移量,则始终使用相同的组ID。

参考:https://www.confluent.io/resources/kafka-the-definitive-guide/