三、Consumer消费者重新分配策略和offset维护机制是什么?
一、消费者根据什么模式从broker获取数据的?
消费者采用 pull 拉取方式,从broker的partition获取数据
为什么是pull模式,而不是broker主动push?
pull 模式则可以根据 consumer 的消费能力进行自己调整,不同的消费者性能不一样。如果broker没有数据,consumer可以配置 timeout 时间,阻塞等待一段时间之后再返回
如果是broker主动push,优点是可以快速处理消息,但是容易造成消费者处理不过来,消息堆积和延迟。
二、消费者从哪个分区进行消费?
一个 topic 有多个 partition,一个消费者组里面有多个消费者,那是怎么分配的?
看下源码中得具体策略实现类
顶层接口:org.apache.kafka.clients.consumer.internals.AbstractPartitionAssignor
round-robin (RoundRobinAssignor非默认策略)
round-robin (RoundRobinAssignor非默认策略)轮询
【按照消费者组】进行轮训分配,同个消费者组监听不同主题也一样,是把所有的 partition 和所有的 consumer 都列出来,
所以消费者组里面订阅的主题是一样的才行,主题不一样则会出现分配不均问题,例如7个分区,同组内2个消费者
正常情况下得消费情况:
topic-p0/topic-p1/topic-p2/topic-p3/topic-p4/topic-p5/topic-p6
c-1(第一个消费者): topic-p0/topic-p2/topic-p4/topic-p6
c-2(第二个消费者):topic-p1/topic-p3/topic-p5
轮询策略得弊端:
如果同一消费者组内,所订阅的消息是不相同的,在执行分区分配的时候不是轮询分配,可能会导致分区分配的不均匀
有3个消费者C0、C1和C2,他们共订阅了 3 个主题:t0、t1 和 t2
t0有1个分区(p0),t1有2个分区(p0、p1),t2有3个分区(p0、p1、p2))
消费者C0订阅的是主题t0,消费者C1订阅的是主题t0和t1,消费者C2订阅的是主题t0、t1和t2
这种极端得情况下,C0只监听了一个,C1也是监听了一个,C2监听了4个。
Range (RangeAssignor默认策略)范围
【按照主题】进行分配,如果不平均分配,则第一个消费者会分配比较多分区, 一个消费者监听不同主题也不影响,例如7个分区,同组内2个消费者
topic-p0/topic-p1/topic-p2/topic-p3/topic-p4/topic-p5//topic-p6
c-1(消费者一): topic-p0/topic-p1/topic-p2/topic-p3
c-2(消费者二):topic-p4/topic-p5/topic-p6
每个主题,每次都会给第一个消费者分配比较多分区,那么当这个消费者监听多个时,第一个消费者会产生积压
Range弊端:
只是针对 1 个 topic 而言,c-1多消费一个分区影响不大
如果有 N 多个 topic,那么针对每个 topic,消费者 C-1 都将多消费 1 个分区,topic越多则消费的分区也越多,则性能有所下降
三、Consumer消费者重新分配策略和offset维护机制是什么?
先提下Rebalance,那么什么是Rebalance呢?
Rebalance 本质上是一种协议,规定了一个 Consumer Group 下的所有 consumer 如何达成一致,来分配订阅 Topic 的每个分区。
例如:某 Group 下有 20 个 consumer 实例,它订阅了一个具有 100 个 partition 的 Topic 。正常情况下,kafka 会为每个 Consumer 平均的分配 5 个分区。这个分配的过程就是 Rebalance。
Rebalance触发的条件:
组成员个数发生变化。例如有新的 consumer 实例加入该消费组或者离开组。
订阅的 Topic 个数发生变化。
订阅 Topic 的分区数发生变化。
在Rebalance发生期间,消费组内消费者无法读取消息。也就是说Rebalance期间的这一小段时间内,消费者组将变得不可用。另外,当一个分区重新分配给另一个消费者时,消费者当前的状态也会丢失。比如消费者消费完某个分区中的一部分消息时还没有来得及提交位移消费者就发生了Rebalance,之后这个分区又被分配给了消费者组内的另一个消费者,原来被消费完的那部分消息又会被重新消费一次,发生重复消费的情况
比如70个分区,10个消费者,但是先启动一个消费者,后续再启动一个消费者,这个会怎么分配?
Kafka 会进行一次分区分配操作,即 Kafka 消费者端的 Rebalance 操作 ,下面都会发生rebalance操作
当消费者组内的消费者数量发生变化(增加或者减少),就会产生重新分配patition
分区数量发生变化时(即 topic 的分区数量发生变化时)
当消费者在消费过程突然宕机了,重新恢复后是从哪里消费,会有什么问题?
消费者会记录offset,故障恢复后从这里继续消费,这个offset记录在哪里?
记录在zk里面和本地,新版默认将offset保证在kafka的内置topic中,名称是 __consumer_offsets
该Topic默认有50个Partition,每个Partition有3个副本,分区数量由参数offset.topic.num.partition配置
通过groupId的哈希值和该参数取模的方式来确定某个消费者组已消费的offset保存到__consumer_offsets主题的哪个分区中
由 消费者组名+主题+分区,确定唯一的offset的key,从而获取对应的值
三元组:group.id+topic+分区号,而 value 就是 offset 的值
__consumer_offsets 的每条消息格式大致如图所示:
考虑到一个 kafka 生成环境中可能有很多 consumer 和 consumer group,如果这些 consumer 同时提交位移,则必将加重 __consumer_offsets 的写入负载,因此 kafka 默认为该 topic 创建了50个分区,并且对每个 group.id 做哈希求模运算,从而将负载分散到不同的 __consumer_offsets 分区上。