Kafka消费者组
什么是kafka消费者组
kafka消费者组(Consumer Group)是kafka提供的可扩展且具有容错性的消费者机制。
它是一个组,所以内部有可以有多个消费者,这些消费者共用一个ID(Group ID),一个组内的所有消费者共同协作,完成对订阅的主题的所有分区进行消费。其中一个主题中的一个分区只能由一个消费者消费。
消费者组的特性
- 一个消费者组可以有多个消费者。
- Group ID是一个字符串,在一个kafka集群中,它标识唯一的一个消费者组。
- 每个消费者组订阅的所有主题中,每个主题的每个分区只能由一个消费者消费。消费者组之间不影响。
为什么出现消费者组
我们知道的消息引擎模型有:点对点模型和发布/订阅模型。传统的消息引擎就是这两大类。这两大类消息引擎,都有各自适合的应用场景,也都有不适应的场景。
点对点的模型,每消费一个消息之后,被消费的消息就会被删除。如果我们需要多个消费者消费同一个消息队列时,就不能使用点对点模型了。
发布订阅模型,支持多个消费者消费同一个消息队列,但是发布订阅模型中,消费者订阅了一个主题后,就要订阅主题的所有分区。这总方式既不灵活,也会影响消息的真是投递效果。
消费者组就避开了上述两种模型的缺陷,有兼容了他们的优点。
首先消费者之间彼此独立,互不影响。可以订阅同一个主题并且互不干扰。再加上Broker端的消息留存机制,kafka的消费者组就完美的解决了上面的问题。kafka使用一种消费者组(Consumer Group)机制,就同时实现了传统消息引擎系统的两大模型:如果所有的消费者实例都属于一个消费者组那就是点对点模型,如果所有消费者实例各自是独立的消费者那就是发布订阅模型。
因为上面消费组的第三个特性。所以消费者组的消费者实例数最好等于该消费者组订阅的主题中的分区数。如果实例数量多于分区数,那多余的实例将永远不会工作,除非有其他实例挂掉。
针对Consumer Group,Kafka如何管理位移(offset)?
这个问题需要区分新老版本。首先他们的存储方式都是使用类似于map的KV对实现的存储。key是分区,v对应Consumer消费该分区的最新位移。我们可以这样理解,但是实际的存储要比这个复杂的多。
新老版本的区别在于位移存储的位置:老版本是将位移存放到zookeeper中,而zookeeper是一个分布式的协调服务框架,kafka重度依赖它实现的各种各样的协调管理。将位移存到zookeeper中的做法,显而易见的好处是减少了kafka broker端的状态保存开销。可以自由的扩缩容,实现超强的伸缩性。
但是由于zookeeper这类元框架其实并不适合进行频繁的写更新。而Consumer Group的位移更新却是一个非常频繁的更新操作。所以并不是很适合将位移存在zookeeper中。
于是新版本将位移保存在kafka内部主题中。就是:_consumer_offsets。
kafka的Rebalance(重平衡)
定义
Rebalance本质上是一种协议,规定了一个Consumer Group下的所有Consumer如何达成一致,来分配订阅Topic的每个分区。例如:某个Group下有20个Consumer实例,它订阅了一个有100个分区的Topic。正常情况下,kafka会给每个实例分配5个分区。这个分配的过程叫做Rebalance。
rebalance发生时,Group下的所有Consumer实例都会协调在一起共同参与。具体怎么分配,是有分配策略协助的。分配策略以后再总结。
触发条件
- 组成员数发生变化。比如有实例进入或者离开组。
- 订阅的主题数发生变更。
- 订阅主题的分区数发生变更。
问题
rebalance有一个比较大的问题。那就是再Rebalance过程中,所有的实例都会停止消费,等Rebalance完成。这就导致Rebalance过程中无法提供服务。而且,Rebalance的过程还很慢。所以我们要尽量避免Rebalance的发生。