zl程序教程

您现在的位置是:首页 >  数据库

当前栏目

kafka---为什么kafka中1个partition只能被同组的一个consumer消费?

2023-04-18 16:25:58 时间


 

Kafka中每一个客户端的offset是由自己进行维护的,kafka并没有对同一个消费组中每个消费者的offset做中心化处理,所以如果他们消费同一个partition 都分别用自己的offset 会出现重复消费的问题。

offset是什么?

offset

partition中的每条消息都被标记了一个序号,每个序号都是连续的,这个序号表示消息在partition中的偏移量,称为offset,每一条消息在partition都有唯一的offset。

offset从语义上来看有两种:Current offset 和 committed offset

Current offset

  • Cuttent offset 保存在客户端中由客户端自己维护,它表示消费者希望收到下一条消息的序号,它仅仅在poll()方法中使用,例如:消费者第一次调用poll()方法收到了20条消息,那么 cuttent offset的值将被设置成20 下一次poll时,kafka就知道要从序号为21的消息开始读取,这样能保证消费者每次poll消息时,收到的消息不重复

Committed offset

  • Committed Offset保存在Broker上 (V0.9之后的版本),它表示Consumer已经确认消费过的消息的序号。主要通过commitSync()来操作。举例:Consumer通过poll()方法收到20条消息后,此时Current Offset就是20,经过一系列的逻辑处理后,并没有调用commitSync()来提交
  • Committed Offset,那么此时Committed Offset依旧是0。
  • Committed Offset主要用于Consumer Rebalance(再平衡)。在Consumer Rebalance的过程中,一个Partition被分配给了一个Consumer,那么这个Consumer该从什么位置开始消费消息呢?答案就是Committed Offset。另外,如果一个Consumer消费了5条消息.(poll并且成功commitSync)之后宕机了,重新启动之后,它仍然能够从第6条消息开始消费,因为Committed Offset已经被Kafka记录为5。
  • Committed Offset是为了每一个消费组进行记录的 不同的消费者组分别记录

小结:

Current offset 是针对消费者 poll过程为了保证每次poll都返回不重复的消息

Committed offset 是为了 Consumer Rebalance(再平衡) 的你过程,它能够保证同一个消费者组中新的消费者在正确的位置开始消费,避免重复消费。

同一消费组内多个消费者同时消费会出现重复消费。例如A1 1-10 POS 10

A2 10-20 POS 20

下次消费的时候 A1是 11-20重复消费

解决方案

  • 假设broker对index进行维护。但是consumer 是进行pull操作的,拉取操作一般来说都是由拉取方提供index,数据方根据index 返回数据。如果由数据方维护index,会增加获取index 的通信开销。
  • 假设consumer端进行多人的index维护,那么就得引入中心的概念,大家都在中心去获得当前的index,这会增加复杂性。
  • 在consumer端维护单人index,可以方便的pull数据。牺牲了分区的分布式消费。由于可以有多个分区,权衡之下是较为合理的方案。