【七】kafka可靠性、有序性、重复消费、丢数据、线程安全

一、哪些情况会造成重复消费

1.生产者挂了重启

场景:

生产者设置的ACK是ALL,及需要所有副本都保存了消息才叫发送成功。

假设生产者发送一条信息,leader已经收到且已经保存了,follower还没来得及同步,leader就挂了。

此时会被认为是发送失败,重发。

而刚好重发的时候旧的leader又重启复活了,那旧的leader会保存两次同样的数据

2.消费者自动提交偏移量

场景

消费者A,第一次poll了100条,刚好第一次提交偏移量也是100+1(5秒提交一次),在后面的3秒中,消费者A又poll了2次,每次100条,相当于此时消费者A已经消费到了偏移量300了,此时才过3秒,还没有到下一次触发自动提交的时间。这是消费者A挂了,发生了消费再平衡,由B来接着消费这个分区,那B就是从101偏移量开始消费,那么101-300都被重复消费了。

3.消费者手动提交偏移量

场景:

如果先拉取消息,消费完后再更新offset位置。然而还没消费完,就报错或者再均衡,那么该次拉取的偏移量就没有提交,就导致会重复消费。

二、哪些情况会造成漏消费

1.生产者没有ACK

场景:

生产者fire-and-forget(发后即忘),无论有几个副本保存了消息,都认为发送成功,那么有可能跟本没副本保存消息

2.生产者ACK=1

场景:

生产者发送消息后,只要有一个副本即leader保存了消息就认为发送成功,那么leader挂了,就会被漏消费

3.生产者ACK=ALL 但是partition副本数量为1

场景:

生产者发送消息后,虽然要等到所有副本都保存了才认为发送成功,但是这里的“所有副本”就只有1个即leader,那么leader挂了就会被漏消费

3.消费者自动提交偏移量

场景:

消费者A,第一次poll了100条,刚好第一次提交偏移量也是100+1(5秒提交一次),但是拉取的这100条才处理了50条,A就挂了,相当于有50条已经拉取了的,已经提交了偏移量了的,还没处理。发生了消费再平衡,由B来接着消费这个分区,B从101开始消费,那么相当于51-101的数据丢失了

4.消费者手动提交偏移量

场景:

先提交位移,但是消息还没消费完就宕机了,造成了消息没有被消费。

三、如何保证可靠性

我理解的可靠性就是保证消息必然送达

1.生产者

ACK=ALL

retries=N 发送失败一直重试

异常时写日志

2.kafka集群

 replication.factor > 1,每个partition至少有2个副本

 min.insync.replicas > 1,每个leader至少和2个follower保持联系

3.消费者

 手动提交偏移量

 消费后才提交偏移量

四、如何保证有序性

1.生产者

发送消息的分区策略,根据Key来指定分区。

有顺序要求的消息,key要一样,即考虑使用业务唯一ID,这样就会被发送到相同的分区中

2.kafka集群

同一个分区中的数据天然有序,分区相当于是个双端队列

3.消费者

同一个主题下的分区,只能被同一个消费者组中的一个消费者消费。

五、线程安全

1.线程封闭,即为每个线程实例化一个 KafkaConsumer 对象

【七】kafka可靠性、有序性、重复消费、丢数据、线程安全

一个线程对应一个 KafkaConsumer 实例,我们可以称之为消费线程。一个消费线程可以消费一个或多个分区中的消息,所有的消费线程都隶属于同一个消费组。

消费逻辑在该消费线程中。

2.消费者程序使用单或多线程获取消息,同时创建多个worker线程执行消息处理逻辑。
获取消息的线程可以是一个,也可以是多个,每个线程维护专属的 KafkaConsumer 实例,处理消息则交由worker线程池来做,从而实现消息获取与消息处理的真正解耦。

两种方式对比

【七】kafka可靠性、有序性、重复消费、丢数据、线程安全