我遇到的情况是将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();
}
答案 0 :(得分:0)
我想在这里要解决几件事。
首先是偏移不同步-这可能是由以下任一原因引起的:
如果poll()
所获取的消息数量不等于normalizedSyslogMessageList
到5000,则commitSync()
仍将运行,而不管当前是否有这批消息是否已处理。
但是,如果大小达到5000,则因为处理是在单独的线程中完成的,所以主使用者线程将永远不会知道该处理是否已完成,但是... commitSync()
无论如何都会运行提交偏移量。
第二部分(我相信这是您的实际关注/问题)-这是否是处理此问题的最佳方法。由于上面的第2点,我会说“否”,即correlationProcessThread
在这里以即兴即忘的方式被调用,所以您不知道这些消息的处理将为您完成的安全地提交偏移量。
这是《卡夫卡权威指南》中的声明-
重要的是要记住,commitSync()将提交最新的 由poll()返回的偏移量,因此请确保您在之后调用commitSync() 您已处理完集合中的所有记录,否则您将承担风险 邮件丢失。
第2点尤其难以修复,因为:
submit()
中使用execute()
而不是ExecutorService
方法来尝试在提交偏移量之前获取处理线程的状态,也需要进行阻塞对correlationProcessThread
的get()方法调用。因此,通过在多个线程中进行处理,您可能不会获得很多好处。用于修复此问题的选项
由于我不了解您的情况和确切要求,因此我只能提出概念性想法,但这可能值得考虑:
我希望这会有所帮助。
答案 1 :(得分:0)
完全同意拉利特所说的话。目前,我正在经历相同的情况,即我的处理分别在不同的线程中进行,而消费者和生产者在不同的线程中进行。我使用了ConcurrentHashMap在生产者线程和使用者线程之间共享,从而更新了是否已处理特定偏移量。
ConcurrentHashMap<OffsetAndMetadata, Boolean>
在使用者方面,可以使用本地LinkedHashMap维护从主题/分区中消费记录的顺序,并在使用者线程本身中进行手动提交。
LinkedHashMap<OffsetAndMetadata, TopicPartition>
如果您的处理线程正在维护任何消耗的记录顺序,则可以参考以下链接。 Transactions in Kafka
在我的方法中要提到的一点是,万一发生任何故障,数据都将被复制。