一、消费者根据什么模式从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
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 每个主题,每次都会给第一个消费者分配比较多分区,那么当这个消费者监听多个时,第一个消费者会产生积压
弊端:
只是针对 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 的分区数发生变化。
问题来了:
例如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 的值



