本文目录
一、前言
在之前的两篇文章里,我们分析了kafka的工作流程、存储机制、分区策略、数据可靠性、故障处理。从而弄清楚了kafka的整体架构以及生产者生产的数据是怎么存储,保证可靠性以及遇到故障时进行处理的。
那么接下来,我们将分析kafka架构里的消费者是如何工作的,本文将重点分析kafka消费者的消费方式,三种分区分配策略(Range分配策略、RoundRobin分配策略、Sticky分配策略) 以及offset的维护。
二、消费者消费方式
先说结论:消费者采用pull(拉)模式从broker中读取数据。
为什么不采用push(推,填鸭式教学)的模式给消费者数据呢?首先回想下咱们上学学习不就是各种填鸭式教学吗?不管你三七二十一,就是按照教学进度给你灌输知识,能不能接受是你的事,并美其名曰:优胜略汰!
这种push方式在kafka架构里显然是不合理的,比如一个broker有多个消费者,它们的消费速率不同,一昧的push只会给消费者带来拒绝服务以及网络拥塞等风险。而kafka显然不可能去放弃速率低的消费者,因此kafka采用了pull的模式,可以根据消费者的消费能力以适当的速率消费broker里的消息。
当然让消费者去pull数据自然也是有缺点的。同样联想上学的场景,如果把学习主动权全部交给学生,那有些学生想学的东西老师那里没有怎么办?那他不就陷入了一辈子就在那不断求索,然而别的也啥都学的这个死循环的状态了。kafka也是这样,采用pull模式后,如果kafka没有数据,消费者可能会陷入循环中,一直返回空数据。为了解决这个问题,Kafka消费者在消费数据时会传入一个时长参数timeout,如果当前没有数据可供消费,消费者会等待一段时间之后再返回,这段时长即为timeout。
三、分区分配策略
我们在第一篇文章里分析了kafka存储数据的分区策略,这里对于消费者来说,一个consumer group中有多个consumer,一个 topic有多个partition,所以肯定会涉及到partition的分配问题,即确定每个partition由哪个consumer来消费,这就是分区分配策略(Partition Assignment Strategy)。
3.1、分配分区的前提条件
首先kafka设定了默认的消费逻辑:一个分区只能被同一个消费组(ConsumerGroup)内的一个消费者消费。
在这个消费逻辑设定下,假设目前某消费组内只有一个消费者C0,订阅了一个topic,这个topic包含6个分区,也就是说这个消费者C0订阅了6个分区,这时候可能会发生下列三种情况:
- 如果这时候消费者组内新增了一个消费者C1,这个时候就需要把之前分配给C0的6个分区拿出来3个分配给C1;
- 如果这时候这个topic多了一些分区,就要按照某种策略,