Scala 卡夫卡-为什么fresh groupId不';当设置自动“偏移量”重置“配置为”时,t返回主题中的所有消息;最新;

Scala 卡夫卡-为什么fresh groupId不';当设置自动“偏移量”重置“配置为”时,t返回主题中的所有消息;最新;,scala,apache-kafka,Scala,Apache Kafka,我尝试在scala中实现一个非常简单的Kafka(0.9.0.1)消费者(代码如下) 就我的理解而言,卡夫卡(或者更好地说是动物园管理员)为每个groupId存储给定主题的最后一条消息的偏移量。因此,考虑到以下情况: 拥有groupId1的消费者昨天只消费了5个 主题中的消息。现在,上次使用的消息的偏移量为4(考虑到 偏移量为0的第一封邮件) 在晚上,两条新消息到达了主题 今天我重新启动消费者,使用相同的groupId1,将 有两种选择: 选项1:如果我将以下属性设置为“latest”,消费者将

我尝试在scala中实现一个非常简单的Kafka(0.9.0.1)消费者(代码如下)

就我的理解而言,卡夫卡(或者更好地说是动物园管理员)为每个groupId存储给定主题的最后一条消息的偏移量。因此,考虑到以下情况:

  • 拥有
    groupId1
    的消费者昨天只消费了5个 主题中的消息。现在,上次使用的消息的偏移量为4(考虑到 偏移量为0的第一封邮件)
  • 在晚上,两条新消息到达了主题
  • 今天我重新启动消费者,使用相同的
    groupId1
    ,将 有两种选择:
  • 选项1:如果我将以下属性设置为
    “latest”
    ,消费者将读取夜间到达的最后2条新消息:

    选项2:如果我将以下属性设置为“最早”,则消费者将阅读主题中的所有7条消息:

    问题:由于某种原因,如果我将消费者的groupId更改为
    groupId2
    ,这是给定主题的新groupId,因此它以前从未使用过任何消息,其最新偏移量应为0。我正期待着通过设置

    props.put(ConsumerConfig.AUTO_OFFSET_RESET_CONFIG, "latest")
    
    使用者将在第一次执行期间读取存储在主题中的所有消息(相当于最早执行)。然后,对于后续执行,它将只消耗新的执行。然而,事实并非如此

    如果我设置了一个新的
    groupId
    ,并将
    AUTO\u OFFSET\u RESET\u CONFIG
    保持为
    latest
    ,消费者将无法阅读任何消息。然后,我需要做的是,第一次运行时,将
    自动偏移量\u重置\u配置设置为
    最早的
    ,一旦groupID的偏移量与0不同,我就可以移动到
    最新的

    我的消费者应该这样做吗?有没有比在我第一次运行消费者后切换
    自动偏移量\u重置\u配置
    更好的解决方案

    以下是我作为简单消费者使用的代码:

    class KafkaTestings {
    
      val brokers = "listOfBrokers"
      val groupId = "anyGroupId"
      val topic = "anyTopic"
    
      val props = createConsumerConfig(brokers, groupId)
    
      def createConsumerConfig(brokers: String, groupId: String): Properties = {
        val props = new Properties()
        props.put(ConsumerConfig.BOOTSTRAP_SERVERS_CONFIG, brokers)
        props.put(ConsumerConfig.GROUP_ID_CONFIG, groupId)
        props.put(ConsumerConfig.ENABLE_AUTO_COMMIT_CONFIG, "true")
        props.put(ConsumerConfig.AUTO_COMMIT_INTERVAL_MS_CONFIG, "1000")
        props.put(ConsumerConfig.SESSION_TIMEOUT_MS_CONFIG, "30000")
        props.put(ConsumerConfig.CLIENT_ID_CONFIG, "12321")
        props.put(ConsumerConfig.AUTO_OFFSET_RESET_CONFIG, "latest")
        props.put(ConsumerConfig.KEY_DESERIALIZER_CLASS_CONFIG, "org.apache.kafka.common.serialization.StringDeserializer")
        props.put(ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG, "org.apache.kafka.common.serialization.StringDeserializer")
        props
      }
    
      def run() = {
        consumer.subscribe(Collections.singletonList(this.topic))
    
        Executors.newSingleThreadExecutor.execute(    new Runnable {
          override def run(): Unit = {
    
            while (true) {
              val records = consumer.poll(1000)
    
              for (record <- records) {
                println("Record: "+record.value)
              }
    
            }
    
          }
        })
      }
    }
    
    object ScalaConsumer extends App {
      val testConsumer = new KafkaTestings()
      testConsumer.run()
    } 
    
    kafkates类{
    val brokers=“经纪人名单”
    val groupId=“anyGroupId”
    val topic=“anyTopic”
    val props=createConsumerConfig(代理,组ID)
    def createConsumerConfig(代理:字符串,组ID:字符串):属性={
    val props=新属性()
    props.put(ConsumerConfig.BOOTSTRAP\u server\u CONFIG,代理)
    props.put(ConsumerConfig.GROUP\u ID\u CONFIG,groupId)
    put(ConsumerConfig.ENABLE\u AUTO\u COMMIT\u CONFIG,“true”)
    props.put(ConsumerConfig.AUTO\u COMMIT\u INTERVAL\u MS\u CONFIG,“1000”)
    props.put(ConsumerConfig.SESSION\u TIMEOUT\u MS\u CONFIG,“30000”)
    props.put(ConsumerConfig.CLIENT\u ID\u CONFIG,“12321”)
    props.put(ConsumerConfig.AUTO\u OFFSET\u RESET\u CONFIG,“最新”)
    put(ConsumerConfig.KEY\u反序列化程序\u CLASS\u配置,“org.apache.kafka.common.serialization.StringDeserializer”)
    put(ConsumerConfig.VALUE\u反序列化程序\u CLASS\u配置,“org.apache.kafka.common.serialization.StringDeserializer”)
    道具
    }
    def run()={
    consumer.subscribe(Collections.singletonList(this.topic))
    Executors.newSingleThreadExecutor.execute(新可运行{
    覆盖def run():单位={
    while(true){
    val记录=消费者投票(1000)
    
    对于(记录这是按照文件规定进行的)

    如果您启动一个新的消费者组(即卡夫卡中没有存储现有偏移量的消费者组),您必须选择消费者是从最早的消息(主题中仍然可用的最早消息)还是从最新的消息(仅从现在开始生成的消息)开始

    有没有比第一次运行消费者后切换自动补偿重置配置更好的解决方案

    您可以最早保留它,因为第二次运行使用者时,它将已经存储了偏移量,并在那里拾取。重置策略仅在创建新使用者组时使用

    今天我重新启动消费者,使用相同的groupId1,将有两个选项:

    不完全是。由于消费者组前一天正在运行,它将找到其已提交的偏移量,并从其停止的位置重新开始。因此,无论您将重置策略设置为什么,它都将收到这两条新消息


    不过,我知道卡夫卡不会永远存储这些偏移量,我相信默认值只有一周。因此,如果你关闭消费者超过一周,这些偏移量可能会过时,你可能会意外地重置为最早(对于大型主题来说,这可能会很昂贵)。鉴于此,可能还是谨慎地将其更改为最新版本。

    您可以最早保留它,因为在第二次运行使用者时,它将已经存储了偏移量,并在那里拾取。重置策略仅在创建新的使用者组时使用。 在我的测试中,我通常希望从最早的偏移量开始读取,但是正如前面提到的,一旦您读取了具有给定groupId的消息,那么您的偏移量将保持在该指针上。 我这样做:


    properties.put(ConsumerConfig.GROUP\u ID\u CONFIG,UUID.randomUUID())

    谢谢您的回答,非常有用。因此,我从您的回答中得出的结论是:最早的将在第一次运行时获取所有偏移量,并从后续运行中获取所有新消息。这实际上是一种完美的行为,因为不需要更改参数。但是,如果偏移量可能老化,则风险很大,因此不要担心关于这种情况,我最了解的是使用最早的运行进行初始运行,然后从后续运行将参数移动到最新运行。我说的对吗?这取决于对您来说更糟糕的情况:重新处理(可能有很多)数据,或遗漏主题中的数据,但在重置过程中跳过。理想情况下,不要丢失这些偏移量…但据我所知,通过切换参数可以避免这两种情况,不是吗?我的意思是
    props.put(ConsumerConfig.AUTO_OFFSET_RESET_CONFIG, "latest")
    
    class KafkaTestings {
    
      val brokers = "listOfBrokers"
      val groupId = "anyGroupId"
      val topic = "anyTopic"
    
      val props = createConsumerConfig(brokers, groupId)
    
      def createConsumerConfig(brokers: String, groupId: String): Properties = {
        val props = new Properties()
        props.put(ConsumerConfig.BOOTSTRAP_SERVERS_CONFIG, brokers)
        props.put(ConsumerConfig.GROUP_ID_CONFIG, groupId)
        props.put(ConsumerConfig.ENABLE_AUTO_COMMIT_CONFIG, "true")
        props.put(ConsumerConfig.AUTO_COMMIT_INTERVAL_MS_CONFIG, "1000")
        props.put(ConsumerConfig.SESSION_TIMEOUT_MS_CONFIG, "30000")
        props.put(ConsumerConfig.CLIENT_ID_CONFIG, "12321")
        props.put(ConsumerConfig.AUTO_OFFSET_RESET_CONFIG, "latest")
        props.put(ConsumerConfig.KEY_DESERIALIZER_CLASS_CONFIG, "org.apache.kafka.common.serialization.StringDeserializer")
        props.put(ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG, "org.apache.kafka.common.serialization.StringDeserializer")
        props
      }
    
      def run() = {
        consumer.subscribe(Collections.singletonList(this.topic))
    
        Executors.newSingleThreadExecutor.execute(    new Runnable {
          override def run(): Unit = {
    
            while (true) {
              val records = consumer.poll(1000)
    
              for (record <- records) {
                println("Record: "+record.value)
              }
    
            }
    
          }
        })
      }
    }
    
    object ScalaConsumer extends App {
      val testConsumer = new KafkaTestings()
      testConsumer.run()
    }