我设法在使用@KafkaListener注释的方法中获取主题/分区/偏移量,但是如何使用这些数据来实现一次性消费者逻辑呢?
我使用ConcurrentKafkaListenerContainerFactory设置concurrenc = 4,并将AckMode设置为MANUAL。 我目前的方法是使用redis进行重复数据删除: 我使用topic:partition作为redis键,offset作为其值,然后比较即将到来的偏移量与redis中的值,如果偏移量比redis更新(大于),则继续使用业务逻辑,否则我忽略该消息。最后提交偏移量(ack.acknowledge())
但是这种方式不起作用,例如,如果在ack.acknowledge()完成之前发生了重新平衡,那么就出现了这个错误:org.apache.kafka.clients.consumer.CommitFailedException,
并且在重新平衡之后,原始分区被分配给另一个线程,这会导致相同的消息被消耗两次。
所以总而言之,如何设计一个可以使每个kafka消息准确传递一次的逻辑?
答案 0 :(得分:2)
你必须在Kafka之外写出原子处理的最后一个偏移量以及处理结果。这可以是数据库或文件,只是不做两次写入,使它成为数据和偏移的单个原子写入。如果您的消费者崩溃并且它或其他实例重新启动或接管,您需要确保首先它读取与最后处理结果一起存储的最后一个偏移量,并在poll()之前搜索()以获取更多消息。这就是现有的Kafka接收器有多少可以实现EOS消耗。
答案 1 :(得分:0)
卡夫卡还不支持一次。它将在0.11.0.0版本中提供:https://issues.apache.org/jira/browse/KAFKA-4923 此版本计划于2017年6月14日发布,因此您可以自行等待或构建此复杂逻辑; - )