[Kafka] Kafka如何保证消息不丢失、不重复
- Kafka基本架构
- Kafka如何保证消息不丢失、不重复
- Kafka消息的丢失和重复可能会发生在哪里?
- Kafka如何保证`生产者端`的消息不丢失、不重复?
- 生产者端`丢失数据`的情况分析
- 生产者端`丢失数据`的解决办法
- 生产者端`重复发送数据`的情况分析及解决办法
- 消费者端`丢失数据`的情况分析及解决办法
- 消费者端`重复消费数据`的情况分析及解决办法
Kafka基本架构
- 生产者Producer :生产信息;
- 消费者Consumer :订阅主题、消费信息;
- 代理Broker : 可以看作是一个独立的 Kafka 实例。多个 Kafka Broker 组成一个卡夫卡集群 Kafka Cluster;
- 主题topic:可以理解为一个队列, 生产者和消费者面向的都是一个 topic, Producer 将消息发送到特定的主题,Consumer 通过订阅特定的主题来消费消息;
- 分区partition: 为了实现扩展性,一个非常大的 topic 可以分布到多个 broker(即服务器)上,一个 topic 可以分为多个 partition,每个 partition 是一个有序的队列。
- 副本Replica: :副本,为保证集群中的某个节点发生故障时,该节点上的 partition 数据不丢失,且 kafka 仍然能够继续工作,kafka 提供了副本机制,一个 topic 的每个分区都有若干个副本,一个 leader 和若干个 follower。
- leader :每个分区多个副本的“主”,生产者发送数据的对象,以及消费者消费数据的对象都是 leader。
- follower :每个分区多个副本中的“从”,实时从 leader 中同步数据,保持和 leader 数据的同步。leader 发生故障时,某个 follower 会成为新的 follower。
Kafka如何保证消息不丢失、不重复
Kafka消息的丢失和重复可能会发生在哪里?
根据以上的Kafka架构图,我们推测一下,消息丢失可能会发生在哪里?
- 生产者
丢失数据
- 消费者
丢失数据
那么消息重复消费可能会发生在哪里?
同样也是在消费者端和生产者端,即:
- 生产者
重复发送数据
- 消费者
重复消费数据
如何保证消息的有序?
- 同步发送模式:发出消息后,必须等待阻塞队列收到通知后,才发送下一条消息;同步发送模式可以保证消息不丢失、又能保证消息的有序性。
- 异步发送模式:生产者一直向缓冲区写消息,然后一起写到队列中;好处是吞吐量大,性能高。
Kafka如何保证生产者端
的消息不丢失、不重复?
生产者端丢失数据
的情况分析
- 生产者端使用同步发送模式,有三种状态保证消息被安全生产,即配置acks参数(默认为1):
●1
:集群的leader节点收到消息后,就可以发回成功写入的通知
●0
:生产者在成功写入消息之前不会等待来着服务器的任何响应,即不在乎消息是否丢失了
●3
:集群中的所有节点都收到消息时,才发回成功写入的通知,这种方式最可靠,但是性能最低
因此,当使用参数1
且leader节点在写入参数时挂掉了,数据就会丢失。 - 使用异步模式时,当缓冲区满了,如果配置为
0
,则还没收到确认的情况下,缓冲区一满就会清空缓冲区中的消息,数据就丢失了
生产者端丢失数据
的解决办法
- 在
同步模式
下,将发送消息的确认机制设置为-1
,使得所有节点确认后再发送下一条数据即可 - 在
异步模式
下,如果消息发送出去了,但还没有收到确定的时候,在配置文件中设置成不限制阻塞超时的时间,即让生产者一直保持等待,也可以保证数据不丢失
生产者端重复发送数据
的情况分析及解决办法
重复发送数据,不用管,在消费者端建立去重表
即可。
消费者端丢失数据
的情况分析及解决办法
如果消息在处理完成前就提交了offset,就有可能造成数据的丢失。解决办法是在后台提交位移前确保消息已经被正常处理了,然后手动提交
offset(调用**commitSync()**函数)。
附注:offset(偏移量)是什么?
Kafka中每一个分区partition都由一系列有序的、不可变的消息组成,这些消息被连续地追加到partition中,partition中的每个消息都有一个连续的序号,用于唯一标识一条消息,offset就记录着下一条将要发送给消费者的消息的序号,offset从语义上来看有两种:
Current Offset
Committed Offset
Current Offset
保存在消费者的客户端中,它表示希望收到的下一条消息的序号,Offset保证每次消费者消费信息时,都能收到正确位置的消息。
Committed Offset
保存在broker上,它表示消费者已经确认消费过的
消息的序号,这个确认需要消费者调用commitSync()函数,如果调用了这个函数,Commit Offset会被更新为Current Offset的值,如果没有调用这个函数,那么它就不会改变,依然是0。它保证新的消费者能够从正确的位置开始消费信息,从而避免重复消费。
消费者端重复消费数据
的情况分析及解决办法
在消费者端建立去重表
即可保证消息只会被消费一次。
附注:Kafka的消息是消费完就消失的吗?
kafka中的数据的删除和消费者是否消费无关,数据的删除只与kafka broker中 的数据保存时间(log.retention.hours=48,数据最大保存48小时)和数据最大保存内存(log.retention.bytes=1073741824,数据最大保存1G)有关。