消费者组

Consumer Group 是 Kafka 提供的可扩展且具有容错性的消费者机制。既然是一个组,那么组内必然可以有多个消费者或消费者实例(Consumer Instance),它 们共享一个公共的 ID,这个 ID 被称为 Group ID。组内的 所有消费者协调在一起来消费订阅主题(Subscribed Topics)的所有分区(Partition)。当然,每个分区只能由同一个消费者组内的一个 Consumer 实例来消费。理解 Consumer Group 记住下面这三个特性。

  1. Consumer Group 下可以有一个或多个 Consumer 实 例。这里的实例可以是一个单独的进程,也可以是同一进程下的线程。在实际场景中,使用进程更为常见一些。
  2. Group ID 是一个字符串,在一个 Kafka 集群中,它标识 唯一的一个 Consumer Group。
  3. Consumer Group 所有实例订阅的主题中的单个分区, 只能分配给组内的某个 Consumer 实例消费。这个分区当然也可以被其他的 Group 消费。

理想情况下, Consumer 实例的数量应该等于该 Group 订阅主题的分区总数。

一个消费者可以消费一个主题的多个分区,但是反过来,一个分区不能被一个消费者组下的多个消费者消费

位移

消费者在消费的过程中需要记录自己 消费了多少数据,即消费位置信息。在 Kafka 中,这个位置 信息有个专门的术语:位移(Offset)。看上去该 Offset 就是一个数值而已,其实对于 Consumer Group 而言,它是一组 KV 对,Key 是分区,V 对应 Consumer 消费该分区的最新位移。

老版本的 Consumer Group 把位移保存在 ZooKeeper 中。Apache ZooKeeper 是一个分布式的协调服务框架,Kafka 重度依赖它实现各种各样的协调管理。将位移保存在 ZooKeeper 外部系统的做法,最显而易见的好处就是减少了 Kafka Broker 端的状态保存开销。现在比较流行的提法是将服务器节点做成无状态的,这样可以自由地扩缩容,实现超强的伸缩性。Kafka 最开始也是基于这样的考虑,才将 Consumer Group 位移保存在独立于 Kafka 集群之外的框架中。

在新版本的 Consumer Group 中,Kafka 社区重新 设计了 Consumer Group 的位移管理方式,采用了将位移保存在 Kafka 内部主题的方法。这个内部主题就是 __consumer_offsets。

重平衡Rebalance

Rebalance 本质上是一种协议,规定了一个 Consumer Group 下的所有 Consumer 如何达成一致,来分配订阅 Topic 的每个分区。比如某个 Group 下有 20 个 Consumer 实例,它订阅了一个具有 100 个分区的 Topic。正常情况下,Kafka 平均会为每个 Consumer 分配 5 个分区。这个分配的过程就叫 Rebalance。

那么 Consumer Group 何时进行 Rebalance 呢? Rebalance 的触发条件有 3 个。

  1. 组成员数发生变更。比如有新的 Consumer 实例加入组 或者离开组,抑或是有 Consumer 实例崩溃被“踢 出”组。
  2. 订阅主题数发生变更。Consumer Group 可以使用正则 表达式的方式订阅主题,比如 consumer.subscribe(Pattern.compile(“t.*c”)) 就表 明该 Group 订阅所有以字母 t 开头、字母 c 结尾的主 题。在 Consumer Group 的运行过程中,你新创建了一 个满足这样条件的主题,那么该 Group 就会发生 Rebalance。
  3. 订阅主题的分区数发生变更。Kafka 当前只能允许增加一 个主题的分区数。当分区数增加时,就会触发订阅该主题 的所有 Group 开启 Rebalance。

Rebalance 发生时,Group 下所有的 Consumer 实例都会 协调在一起共同参与。你可能会问,每个 Consumer 实例怎么知道应该消费订阅主题的哪些分区呢?这就需要分配策略的协助了。

当前 Kafka 默认提供了 3 种分配策略,每种策略都有一定 的优势和劣势.

Rebanlance不好的地方在于

首先,Rebalance 过程对 Consumer Group 消费过程有极 大的影响。Rebalance 过程和JVM 类似,在 Rebalance 过程中,所有 Consumer 实例都会停 止消费,等待 Rebalance 完成。这是 Rebalance 为人诟病 的一个方面。

其次,目前 Rebalance 的设计是所有 Consumer 实例共同 参与,全部重新分配所有分区。其实更高效的做法是尽量减 少分配方案的变动。

最后,Rebalance 实在是太慢了。曾经,有个国外用户的 Group 内有几百个 Consumer 实例,成功 Rebalance 一 次要几个小时!