kafka教程-消费者分区分配策略(Range、RoundRobin、Sticky)

提出问题

下图,主题中有 3 个分区,消费者组中有 3 个消费者,哪个消费者消费哪个分区的消息?

这就涉及到 Kafka 消费者的 分区分配策略

分区分配策略

一个 consumer group 中有多个 consumer,一个 topic 有多个 partition

有两种策略,决定哪个 partition 由哪个 consumer 来消费:

  • Range,范围分区,默认使用
  • RoundRobin,轮询分区
  • sticky

Range

让 所有 consumer 平均消费 partition

默认策略

对同一个topic中的 partition 按照序号排序,并对 consumer 按照字典顺序排序

为每个consumer划分固定的分区范围,如果不够平均分配,那么排序靠前的 consumer 会 多分配分区

如下图:因为 10除3除不尽,所以 consumer0 会多分配一个分区

缺点

如上,只是针对 1 个 topic 而言,消费者 consumer0 多消费1个分区影响不是很大。
如果有 N 多个 topic,那么针对每个 topic,消费者 consumer0 都将多消费 1 个分区,topic越多,consumer0 消费的分区会比其他消费者 多消费 N 个分区。

这就是 Range 范围分区的一个很明显的弊端了

解决:可通过 RoundRobin 轮询分区策略

RoundRobin

将消费组内所有消费者,消费者订阅的所有主题的分区按照字典序排序,然后通过轮询方式逐个将分区依次分配给每个消费者。

情况一

同一个消费组内,所有的消费者的订阅信息都是 相同 的,那么分区分配是 均匀 的

例子

消费组中有2个消费者,都订阅了主题 t0 和 t1,并且每个主题都有 3 个分区

订阅的所有分区可以标识为:t0p0、t0p1、t0p2、t1p0、t1p1、t1p2

分配结果如下图:

消费者C0:t0p0、t0p2、t1p1
消费者C1:t0p1、t1p0、t1p2

情况二

同一个消费组内,所有的消费者的订阅信息 不相同,那么在执行分区分配的时候就不是完全的轮询分配,有可能导致分区分配得 不均匀

例子

同一消费者组中,有3个消费者 C0、C1 和 C2,他们共订阅了 3 个主题:

  • t0,有1个分区(p0)
  • t1,有2个分区(p0、p1)
  • t2,有3个分区(p0、p1、p2))

分区情况如下图:

消费者C0:t0p0
消费者C1:t1p0
消费者C2:t1p1、t2p0、t2p1、t2p2

缺点

从情况二可以看到 RoundRobinAssignor 策略也不是十分完美,这样分配其实并不是最优解

类

org.apache.kafka.clients.consumer.RoundRobinAssignor

Sticky

sticky 这个单词可以翻译为“黏性的”,Kafka 从 0.11.x 版本开始引入这种分配策略

目标:

  • 分区的分配要尽可能均匀
  • 分区的分配尽可能与上次分配的保持相同

当两者发生冲突时,第一个目标优先于第二个目标。鉴于这两个目标,StickyAssignor 分配策略的具体实现要复杂得多。

情况一:订阅信息相同

例子

消费组内有3个消费者(C0、C1 和 C2),它们都订阅了4个主题(t0、t1、t2、t3),并且每个主题有2个分区。也就是说,整个消费组订阅了 t0p0、t0p1、t1p0、t1p1、t2p0、t2p1、t3p0、t3p1 这8个分区。

分配结果如下图:

消费者C0:t0p0、t1p1、t3p0
消费者C1:t0p1、t2p0、t3p1
消费者C2:t1p0、t2p1

看上去似乎与采用 RoundRobinAssignor 分配策略所分配的结果相同

例子2

假设此时消费者 C1 脱离了消费组,那么消费组就会执行再均衡操作,进而消费分区会重新分配。

分配结果如下图:

消费者C0:t0p0、t1p1、t3p0、t2p0
消费者C2:t1p0、t2p1、t0p1、t3p1

可以看到分配结果中 保留了上一次分配 中对消费者 C0 和 C2 的所有分配结果,并将原来消费者 C1 的分区分配给了剩余的两个消费者 C0 和 C2,最终 C0 和 C2 的分配还保持了均衡。

情况二:订阅信息不同

同样消费组内有3个消费者(C0、C1 和 C2),集群中有3个主题(t0、t1 和 t2),这3个主题分别有1、2、3个分区。

也就是说,集群中有 t0p0、t1p0、t1p1、t2p0、t2p1、t2p2 这6个分区。消费者 C0 订阅了主题 t0,消费者 C1 订阅了主题 t0 和 t1,消费者 C2 订阅了主题 t0、t1 和 t2

分配结果如下图:

消费者C0:t0p0
消费者C1:t1p0、t1p1
消费者C2:t2p0、t2p1、t2p2

可以看到这才是一个最优解(消费者 C0 没有订阅主题 t1 和 t2,所以不能分配主题 t1 和 t2 中的任何分区给它,对于消费者 C1 也可同理推断)

参考:
https://blog.csdn.net/qq_21383435/article/details/108720155
https://cloud.tencent.com/developer/article/1791969


原文出处:/show_1IX4WGfvTBk5.html