Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/324.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
Java Kafka enable.auto.commit false与commitSync()结合使用_Java_Apache Kafka - Fatal编程技术网

Java Kafka enable.auto.commit false与commitSync()结合使用

Java Kafka enable.auto.commit false与commitSync()结合使用,java,apache-kafka,Java,Apache Kafka,我遇到了一个场景,enable.auto.commit被设置为false。对于每个poll(),获得的记录都会卸载到threadPoolExecutor。而commitSync()是在上下文之外发生的。但是,我怀疑这是否是正确的处理方法,因为在我提交消息时,我的线程池可能仍然处理很少的消息 while (true) { ConsumerRecords < String, NormalizedSyslogMessage > records = consumer.poll(100);

我遇到了一个场景,
enable.auto.commit
被设置为
false
。对于每个
poll()
,获得的记录都会卸载到
threadPoolExecutor
。而
commitSync()
是在上下文之外发生的。但是,我怀疑这是否是正确的处理方法,因为在我提交消息时,我的线程池可能仍然处理很少的消息

while (true) {
 ConsumerRecords < String, NormalizedSyslogMessage > records = consumer.poll(100);
 Date startTime = Calendar.getInstance().getTime();
 for (ConsumerRecord < String, NormalizedSyslogMessage > record: records) {
  NormalizedSyslogMessage normalizedMessage = record.value();
  normalizedSyslogMessageList.add(normalizedMessage);
 }
 Date endTime = Calendar.getInstance().getTime();
 long durationInMilliSec = endTime.getTime() - startTime.getTime();
 // execute process thread on message size equal to 5000 or timeout > 4000
 if (normalizedSyslogMessageList.size() == 5000) {
  CorrelationProcessThread correlationProcessThread = applicationContext
   .getBean(CorrelationProcessThread.class);
  List < NormalizedSyslogMessage > clonedNormalizedSyslogMessages = deepCopy(normalizedSyslogMessageList);
  correlationProcessThread.setNormalizedMessage(clonedNormalizedSyslogMessages);
  taskExecutor.execute(correlationProcessThread);
  normalizedSyslogMessageList.clear();
 }
 consumer.commitSync();
}
while(true){
ConsumerRecordsrecords=consumer.poll(100);
Date startTime=Calendar.getInstance().getTime();
对于(ConsumerRecordrecord:records){
NormalizedSyslogMessage normalizedMessage=record.value();
normalizedSyslogMessageList.add(normalizedMessage);
}
Date endTime=Calendar.getInstance().getTime();
long DurationInMilliesec=endTime.getTime()-startTime.getTime();
//在消息大小等于5000或超时>4000时执行进程线程
if(normalizedSyslogMessageList.size()==5000){
CorrelationProcessThread CorrelationProcessThread=applicationContext
.getBean(CorrelationProcessThread.class);
ListclonedNormalizedSyslogMessages=deepCopy(normalizedSyslogMessageList);
correlationProcessThread.SetNormalizedMessages(clonedNormalizedSyslogMessages);
taskExecutor.execute(correlationProcessThread);
normalizedSyslogMessageList.clear();
}
consumer.commitSync();
}

我想这里有几件事需要解决

首先是偏移量不同步-这可能是由以下任一原因造成的:

  • 如果
    poll()
    获取的消息数没有将
    normalizedSyslogMessageList
    的大小设置为5000,则无论当前批消息是否已处理,
    commitSync()
    仍将运行

  • 但是,如果大小达到5000-因为处理是在单独的线程中完成的,主使用者线程将永远不知道处理是否已完成,但。。。
    commitSync()
    无论如何都会运行,以提交偏移量

  • 第二部分(我相信这是您真正关心的问题)这是否是处理这一问题的最佳方式。我之所以说不,是因为上面的第2点,也就是说,
    correlationProcessThread
    在这里以一种“火而忘”的方式被调用,所以您不知道这些消息的处理将在何时完成,以便您能够安全地提交偏移量

    以下是《卡夫卡权威指南》中的声明-

    记住commitSync()将提交最新的 poll()返回的偏移量,因此请确保在 您已完成对集合中所有记录的处理,否则您将面临风险 丢失的消息

    while (true) {
     ConsumerRecords < String, NormalizedSyslogMessage > records = consumer.poll(100);
     Date startTime = Calendar.getInstance().getTime();
     for (ConsumerRecord < String, NormalizedSyslogMessage > record: records) {
      NormalizedSyslogMessage normalizedMessage = record.value();
      normalizedSyslogMessageList.add(normalizedMessage);
     }
     Date endTime = Calendar.getInstance().getTime();
     long durationInMilliSec = endTime.getTime() - startTime.getTime();
     // execute process thread on message size equal to 5000 or timeout > 4000
     if (normalizedSyslogMessageList.size() == 5000) {
      CorrelationProcessThread correlationProcessThread = applicationContext
       .getBean(CorrelationProcessThread.class);
      List < NormalizedSyslogMessage > clonedNormalizedSyslogMessages = deepCopy(normalizedSyslogMessageList);
      correlationProcessThread.setNormalizedMessage(clonedNormalizedSyslogMessages);
      taskExecutor.execute(correlationProcessThread);
      normalizedSyslogMessageList.clear();
     }
     consumer.commitSync();
    }
    
    第2点尤其难以修复,因为:

    • 向池中的线程提供使用者引用基本上意味着多个线程试图访问一个使用者实例(提到了这种方法和问题——主要是Kafka使用者不具备线程安全性)
    • 即使您尝试在提交偏移量之前使用
      submit()
      方法而不是
      executeService
      中的
      execute()
      获取处理线程的状态,您也需要对
      correlationProcessThread
      进行阻塞get()方法调用。因此,在多个线程中处理可能不会带来很多好处
    修复此问题的选项

    由于我不了解您的背景和确切要求,我只能提出概念性的想法,但可能值得考虑:

    • 根据使用者实例需要执行的处理中断使用者实例,并在同一线程或线程中执行处理
    • 您可以探索在映射中维护消息偏移量的可能性(在处理它们时),然后提交这些特定偏移量()

    我希望这能有所帮助。

    完全同意Lalit所提到的。目前,我正在经历同样的情况,我的处理在不同的线程中进行,消费者和生产者在不同的线程中进行。我使用了一个ConcurrentHashMap在生产者线程和消费者线程之间共享,它更新特定偏移量是否已被处理

    ConcurrentHashMap<OffsetAndMetadata, Boolean>
    
    ConcurrentHashMap
    
    在使用者端,可以使用本地LinkedHashMap来维护从主题/分区消费记录的顺序,并在使用者线程本身中进行手动提交

    LinkedHashMap<OffsetAndMetadata, TopicPartition>
    
    LinkedHashMap
    
    如果处理线程正在维护任何消耗的记录顺序,则可以参考以下链接。

    在我的方法中需要提到的一点是,如果出现任何故障,数据都有可能被复制