1. 消费者组概念:什么是消费者组、消费者组的作用、消费者组与分区的关系
1.1 什么是消费者组
消费者组,说白了就是一组消费者实例的集合。它们共享一个 group.id,协同消费一个或多个主题的数据。
我个人习惯把消费者组想象成一个「工作小组」。小组里的每个人(消费者实例)各自负责一部分任务(分区),大家互不干扰,合起来又能把整个任务做完。
举个例子:你有一个主题叫 order_events,分了 6 个分区。你起了 3 个消费者实例,都设置 group.id = "order-group"。那么 Kafka 会自动把这 6 个分区分配给 3 个消费者,每人分到 2 个。
核心定义:消费者组是 Kafka 实现点对点消费模型的基本单元。同一个组内的消费者,不会重复消费同一条消息。
1.2 消费者组的作用
消费者组解决了两个关键问题:水平扩展和故障容错。
- 水平扩展:当消费速度跟不上生产速度时,加消费者实例就行。组内会自动重新分配分区,把负载分摊出去。
- 故障容错:某个消费者挂了,组内其他消费者会接管它负责的分区。整个过程对业务代码透明。
我在项目中遇到过这样一个场景:双十一大促期间,订单消息量暴涨 10 倍。我们什么都没改,就加了几台消费者机器,分区自动重平衡,消费延迟立刻降下来了。这就是消费者组带来的好处。
避坑指南:我曾经以为消费者实例越多越好,结果发现分区数有限,消费者超过分区数时,多余的实例会闲置。所以消费者实例数不要超过分区总数。
1.3 消费者组与分区的关系
这是理解消费者组最核心的部分。我画了一张图,你看完就明白了。
这张图展示了最核心的关系:
- 一个主题的多个分区,被均匀分配给组内的消费者实例
- 每个分区只能被组内的一个消费者消费
- 一个消费者可以消费多个分区
注意:如果消费者实例数大于分区数,多出来的实例会一直空闲。这不是 Bug,是设计如此——Kafka 保证每个分区只被一个消费者消费,不会出现多个消费者抢同一个分区的情况。
1.4 分区分配策略
Kafka 提供了几种分区分配策略,我挑最常用的两种说一下:
| 策略名称 | 分配方式 | 适用场景 |
|---|---|---|
| RangeAssignor | 按主题分区,每个主题独立分配 | 分区数均匀,消费者订阅相同主题 |
| RoundRobinAssignor | 所有分区统一轮询分配 | 消费者订阅多个主题,希望负载更均衡 |
| StickyAssignor | 尽量保持已有分配不变 | 频繁重平衡场景,减少分区移动 |
我个人习惯用 StickyAssignor。为什么?因为生产环境中重平衡是常态,Sticky 策略能最大程度减少分区在消费者之间的「搬家」,降低不必要的开销。
经验之谈:我曾经在一个 200 个分区、20 个消费者的集群上,因为默认的 Range 策略导致每次重平衡都要移动大量分区。换成 Sticky 后,重平衡时间从 30 秒降到了 5 秒以内。
1.5 消费者组的生命周期
一个消费者组从创建到销毁,大致经历这几个阶段:
- 加入组:消费者向协调器(Coordinator)发送 JoinGroup 请求
- 选组长:协调器选出一个消费者作为 Group Leader
- 分配分区:Leader 根据分配策略,决定每个消费者负责哪些分区
- 同步分配:Leader 把分配结果发给协调器,协调器广播给所有消费者
- 开始消费:每个消费者开始拉取自己负责的分区的消息
嗯,这里要注意:如果消费者心跳超时或者主动离开,会触发重平衡(Rebalance),重新走一遍上面的流程。
一句话总结:消费者组是 Kafka 实现「水平扩展 + 故障容错」的基石。理解分区与消费者的映射关系,是掌握消费者组负载均衡的第一步。