Kafka导致重复消费原因和解决方案,看这儿~

169 篇文章 0 订阅
142 篇文章 0 订阅

image

问题分析

导致kafka的重复消费问题原因在于,已经消费了数据,但是offset没来得及提交(比如Kafka没有或者不知道该数据已经被消费)。

总结以下场景导致Kakfa重复消费:

原因1:强行kill线程,导致消费后的数据,offset没有提交(消费系统宕机、重启等)。

原因2:设置offset为自动提交,关闭kafka时,如果在close之前,调用 consumer.unsubscribe() 则有可能部分offset没提交,下次重启会重复消费。

例如:

try {
    consumer.unsubscribe();
} catch (Exception e) {
}

try {
    consumer.close();
} catch (Exception e) {
}

上面代码会导致部分offset没提交,下次启动时会重复消费。

解决方法:设置offset自动提交为false

整合了Spring配置的修改如下配置

spring配置:

spring.kafka.consumer.enable-auto-commit=false
spring.kafka.consumer.auto-offset-reset=latest

整合了API方式的修改enable.auto.commit为false

API配置:

Properties props = new Properties();
props.put("bootstrap.servers", "localhost:9092");
props.put("group.id", "test");
props.put("enable.auto.commit", "false");

一旦设置了 enable.auto.commit 为 true,Kafka 会保证在开始调用 poll 方法时,提交上次 poll 返回的所有消息。从顺序上来说,poll 方法的逻辑是先提交上一批消息的位移,再处理下一批消息,因此它能保证不出现消费丢失的情况。

原因3:(重复消费最常见的原因):消费后的数据,当offset还没有提交时,partition就断开连接。比如,通常会遇到消费的数据,处理很耗时,导致超过了Kafka的session timeout时间(0.10.x版本默认是30秒),那么就会re-blance重平衡,此时有一定几率offset没提交,会导致重平衡后重复消费。

原因4:当消费者重新分配partition的时候,可能出现从头开始消费的情况,导致重发问题。

原因5:当消费者消费的速度很慢的时候,可能在一个session周期内还未完成,导致心跳机制检测报告出问题。

原因6:并发很大,可能在规定的时间(session.time.out默认30s)内没有消费完,就会可能导致reblance重平衡,导致一部分offset自动提交失败,然后重平衡后重复消费

问题描述:

我们系统压测过程中出现下面问题:异常rebalance,而且平均间隔3到5分钟就会触发rebalance,分析日志发现比较严重。错误日志如下:

08-09 11:01:11 131 pool-7-thread-3 ERROR [] - 
commit failed 
org.apache.kafka.clients.consumer.CommitFailedException: Commit cannot be completed since the group has already rebalanced and assigned the partitions to another member. This means that the time between subsequent calls to poll() was longer than the configured max.poll.interval.ms, which typically implies that the poll loop is spending too much time message processing. You can address this either by increasing the session timeout or by reducing the maximum size of batches returned in poll() with max.poll.records.
        at org.apache.kafka.clients.consumer.internals.ConsumerCoordinator.sendOffsetCommitRequest(ConsumerCoordinator.java:713) ~[MsgAgent-jar-with-dependencies.jar:na]
        at org.apache.kafka.clients.consumer.internals.ConsumerCoordinator.commitOffsetsSync(ConsumerCoordinator.java:596) ~[MsgAgent-jar-with-dependencies.jar:na]
        at org.apache.kafka.clients.consumer.KafkaConsumer.commitSync(KafkaConsumer.java:1218) ~[MsgAgent-jar-with-dependencies.jar:na]
        at com.today.eventbus.common.MsgConsumer.run(MsgConsumer.java:121) ~[MsgAgent-jar-with-dependencies.jar:na]
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) [na:1.8.0_161]
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) [na:1.8.0_161]
        at java.lang.Thread.run(Thread.java:748) [na:1.8.0_161]

这个错误的意思是,消费者在处理完一批poll的消息后,在同步提交偏移量给broker时报的错。初步分析日志是由于当前消费者线程消费的分区已经被broker给回收了,因为kafka认为这个消费者死了,那么为什么呢?

问题分析:

这里就涉及到问题是消费者在创建时会有一个属性max.poll.interval.ms(默认间隔时间为300s),

该属性意思为kafka消费者在每一轮poll()调用之间的最大延迟,消费者在获取更多记录之前可以空闲的时间量的上限。如果此超时时间期满之前poll()没有被再次调用,则消费者被视为失败,并且分组将重新平衡,以便将分区重新分配给别的成员。

处理重复数据

因为offset此时已经不准确,生产环境不能直接去修改offset偏移量。

所以重新指定了一个消费组(group.id=order_consumer_group),然后指定auto-offset-reset=latest这样我就只需要重启我的服务了,而不需要动kafka和zookeeper了!

#consumer
spring.kafka.consumer.group-id=order_consumer_group
spring.kafka.consumer.key-deserializer=org.apache.kafka.common.serialization.StringDeserializer
spring.kafka.consumer.value-deserializer=org.apache.kafka.common.serialization.StringDeserializer
spring.kafka.consumer.enable-auto-commit=false
spring.kafka.consumer.auto-offset-reset=latest

注:如果你想要消费者从头开始消费某个topic的全量数据,可以重新指定一个全新的group.id=new_group,然后指定auto-offset-reset=earliest即可

欢迎关注微信公众号【慕容千语】

Kafka重复消费指的是消费者可能会在某些情况下重复消费相同的消息。Kafka 是一个分布式消息系统,它的消费者组可以有多个消费者同消费同一个主题的消息。当某个消费消费一条消息Kafka 就会将该消息的 offset 值保存在消费者组的 offset 管理器中。这样,其他消费者就可以从该 offset 值开始消费后续的消息。 Kafka重复消费可能发生在以下几种情况下: 1. 消费者手动重置 offset:如果消费者手动将 offset 重置到之前已经消费过的位置,那么接下来消费者就会重新消费之前已经消费过的消息。 2. 消费者组 rebalance:当消费者组发生 rebalance 消费者会重新分配分区。如果一个消费者之前消费了某个分区的消息,但在 rebalance 后该分区被分配给了另一个消费者,那么该消费者就会重新消费该分区之前已经消费过的消息。 3. 消息重复发送:在某些情况下,生产者可能会重复发送相同的消息。如果消费者在消费该消息出现了异常,那么该消息就可能被重复消费。 为了避免 Kafka重复消费,可以考虑使用以下几种策略: 1. 自动管理 offset:Kafka 提供了自动管理 offset 的功能,消费者可以将 offset 保存在 Kafka 中,这样就可以避免手动重置 offset 的问题。 2. 避免 rebalance:可以通过调整消费者组的配置来避免 rebalance 的频繁发生。 3. 消费幂等性:消费者可以实现消费幂等性,即使消息重复消费也不会对系统产生影响。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值