Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/apache-kafka/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Apache kafka Kafka使用者偏移提交检查,以避免提交较小的偏移_Apache Kafka_Kafka Consumer Api - Fatal编程技术网

Apache kafka Kafka使用者偏移提交检查,以避免提交较小的偏移

Apache kafka Kafka使用者偏移提交检查,以避免提交较小的偏移,apache-kafka,kafka-consumer-api,Apache Kafka,Kafka Consumer Api,我们假设有一个消费者发送提交偏移量10的请求。 如果存在通信问题,并且代理没有收到请求,当然也没有响应。之后,我们有另一个消费者处理另一批,并成功提交了抵销20 Q:我想知道是否有一种方法或属性可以处理,这样我们可以在提交偏移量20之前检查日志中的上一个偏移量是否已提交?您描述的场景只能在使用异步提交时发生 请记住,一个特定的TopicPartition只能由同一个ConsumerGroup中的单个使用者使用。如果您有两个使用者在阅读同一个TopicPartition,那么这是唯一可能的 如果他

我们假设有一个消费者发送提交偏移量10的请求。 如果存在通信问题,并且代理没有收到请求,当然也没有响应。之后,我们有另一个消费者处理另一批,并成功提交了抵销20


Q:我想知道是否有一种方法或属性可以处理,这样我们可以在提交偏移量20之前检查日志中的上一个偏移量是否已提交?

您描述的场景只能在使用异步提交时发生

请记住,一个特定的TopicPartition只能由同一个ConsumerGroup中的单个使用者使用。如果您有两个使用者在阅读同一个TopicPartition,那么这是唯一可能的

  • 如果他们有不同的消费者群体,或者
  • 如果他们拥有相同的ConsumerGroup,就会发生重新平衡。但是,一次只有一个使用者会读取该主题分区,而不会同时读取这两个分区
  • 案例#1非常清楚:如果他们有不同的ConsumerGroup,那么他们将并行和独立地使用分区。此外,它们的comitted偏移量是单独管理的

    案例#2:如果第一个使用者由于使用者失败/死亡且未恢复而未能提交偏移量10,则将发生使用者重新平衡,另一个活动使用者将拾取该分区。由于未提交偏移量10,新使用者将再次开始读取偏移量10,然后再跳到下一批,并可能提交偏移量20。这导致“至少一次”语义,并可能导致重复

    现在,我们来看一个场景,在提交更高的偏移量之后,您可以提交更小的偏移量。正如一开始所说的,如果异步提交偏移量(使用
    commitAsync
    ),则确实可能发生这种情况。设想以下场景,按时间顺序排列:

    • 使用者读取偏移量0(后台线程尝试提交偏移量0)
    • 提交偏移量0成功
    • 使用者读取偏移量1(后台线程尝试提交偏移量1)
    • 提交偏移量1失败,请稍后重试
    • 使用者读取偏移量2(后台线程尝试提交偏移量2)
    • 提交偏移量2成功
    • 现在,如何处理(您正在尝试提交偏移量1?)
    如果您让重试机制再次提交偏移量1,则看起来您的使用者仅在偏移量1之前提交。这是因为在最新的偏移PAR TopCiffice分区上的每个消费者组的信息存储在内部压缩的卡夫卡主题中,这是为了只为我们的消费者组存储最新的值(在我们的例子中是偏移1)。 在《卡夫卡——权威指南》一书中,有一个关于如何缓解这一问题的提示:

    重试异步提交:为异步重试获得正确的提交顺序的一个简单模式是使用单调递增的序列号。每次提交时增加序列号,并在提交到commitAsync回调时添加序列号。准备发送重试时,请检查回调得到的提交序列号是否等于实例变量;如果是,则没有新的提交,可以安全地重试。如果实例序列号较高,请不要重试,因为已发送较新的提交

    例如,您可以在下面的Scala中看到这一思想的实现:

    import java.util_
    导入java.time.Duration
    导入org.apache.kafka.clients.consumer.{ConsumerConfig,ConsumerRecord,KafkaConsumer,OffsetAndMetadata,OffsetCommitCallback}
    导入org.apache.kafka.common.{KafkaException,TopicPartition}
    导入collection.JavaConverters_
    对象AsyncCommitWithCallback扩展应用程序{
    //定义主题
    val topic=“myOutputTopic”
    //设置属性
    val props=新属性()
    props.put(ConsumerConfig.GROUP\u ID\u CONFIG,“AsyncCommitter5”)
    put(ConsumerConfig.BOOTSTRAP\u SERVERS\u CONFIG,“localhost:9092”)
    //[设置更多属性…]
    //创建KafkaConsumer并订阅
    val consumer=new KafkaConsumer[String,String](道具)
    consumer.subscribe(列表(主题).asJavaCollection)
    //初始化全局计数器
    val atomicLong=新的atomicLong(0)
    //消费信息
    试一试{
    while(true){
    val记录=消费者投票(百万持续时间(1)).asScala
    if(记录非空){
    用于(数据例如printStackTrace()
    }最后{
    consumer.commitSync()
    consumer.close()
    }
    类KeepOrderAsyncCommit扩展了OffsetCommitCallback{
    //保持此回调实例的位置
    val position=atomicLong.incrementAndGet()
    覆盖def onComplete(偏移量:util.Map[TopicPartition,OffsetAndMetadata],异常:异常):单位={
    //仅当没有其他提交增加全局计数器时重试
    if(异常!=null){
    if(position==atomicLong.get){
    consumer.commitAsync(此)
    }
    }
    }
    }
    }