kafka consumer

消费模式

  • pull(拉)模式:consumer采用从broker中主动拉取数据。Kafka采用这种方式。
  • push(推)模式:Kafka没有采用这种方式,因为由broker 决定消息发送速率,很难适应所有消费者的消费速率。pull模式不足之处是,如果Kafka没有数 据,消费者可能会陷入循环中,一直返回空数据。针对这一点,Kafka 的消费者在消费数据时会传入一个超时参数 timeout,如果当前没有数据可供消费,consumer 会等待一段时间之后再返回。

消费者工作流程

消费者组原理

       Consumer Group  (CG) :消费者组, 由多个consumer组成。组成一个消费者组的条件,是所有消费者拥有相同的groupid。消费者组内每个消费者负责消费不同分区的数据,一个分区只能由一个组内消费者消费。消费者组之间互不影响。所有的消费者都属于某个消费者组。

注意:如果向消费组中添加的消费者,超过主题分区数量,则有一部分消费者就会闲 置,不会接收任何消息。

 消费者组初始化流程
        coordinator:辅助实现消费者组的初始化和分区的分配。coordinator节点选择 = groupid的hashcode值 % 50  ( __consumer_offsets的分区数量)。例如:   groupid的hashcode值= 1 ,1% 50 = 1,那么 就选择 __consumer_offsets 为1号分区的coordinator的那个broker 作为这个消费者组的老大。消费者组下的所有的消费者提交offset的时候就往这个分区去提交offset。

 分区的分配策略

一个consumer group中由多个consumer组成,  一个 topic由多个partition组成,  一个partition到底由哪个consumer来消费。

Kafka有四种分区分配策略:   Range、RoundRobin、Sticky、CooperativeSticky。可以通过配置参数partition.assignment.strategy,修改分区的分配策略。kafka3.x版本后(含)默认策略是Range +  CooperativeSticky。Kafka可以同时使用多个分区分配策略。

1)Range:Range 对每个 topic 而言,首先对同一个 topic 里面的分区按照序号进行排序,并 对消费者按照字母顺序进行排序,假如现在有 5 个分区,  3 个消费者,排序后的分区将会 是0,1,2,3,4,消费者排序完之后将会是C0,C1,C2。通过 partitions数/consumer数 来决定每个消费者应该 消费几个分区。  如果除不尽,那么前面的消费者将会多消费 1 个分区。5/3 = 1 余 2 ,除不尽,那么 消费者 C0 和 C1 会多 消费 1 个分区。

注意:  如果只是针对 1 个 topic ,  C0和C1多消费1个分区影响不大。但是如果有 N 个 topic,那么针对每个 topic,消费者C0和C1都多消费 1 个分区,topic越多,  C0 和 C1消 费的分区会比其他消费者明显多 N 个分区。容易产生数据倾斜!

​​​​​​2)RoundRobin :RoundRobin 针对集群中所有Topic而言。使用轮询分区策略,是把所有的 partition 和所有的 consumer 都列出来,然后按照 hashcode 进行排序,最后 通过轮询算法来分配 partition 给到各个消费者。 

        如果同一消费者组内,所订阅的消息是不相同的,那么在执行分区分配的时候,就不是完全的轮询分配,有可能会导致分区分配的不均匀 例如:同一消费组中,有3个消费者C0、C1和C2,他们共订阅了 3 个主题:t0、t1 和 t2,这 3 个主题分别有 1、2、3 个分区(即:t0有1个分区(p0),t1有2个分区(p0、p1),t2有3个分区(p0、p1、p2)),整个消费者所订阅的所有分区可以标识为 t0p0、t1p0、t1p1、t2p0、t2p1、t2p2。具体而言,消费者C0订阅的是主题t0,消费者C1订阅的是主题t0和t1,消费者C2订阅的是主题t0、t1和t2,最终分区分配结果如下:

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


​​​​​​3)Sticky :可以理解为分配的结果带有“粘性的”。即在执行一次新的分配之前,保证在尽可能多地保留现有分区分配的同时,最大限度地平衡分配,可以节省开销。粘性分区是 Kafka 从 0. 11.x 版本开始引入这种分配策略,首先会尽量均衡的将分区分配给消费者,在消费者组内的消费者出现问题的时候,会尽量保持原有分配的分区不变化。

分区分配再平衡

Range:假设topic1 有5个分区  3个消费者实例  那么会按照
0号消费者  消费0、1两个分区;
1号消费者消费2、3 两个分区;
2号消费者消费分区 4的数据。
如果0号消费者宕机 则此时触发再平衡。 0 号消费者的任务会整体被分配到 1 号消费者或者 2 号消费者。再平衡的结果为:

1 号消费者: 消费到 0、1、2 号分区数据。
2 号消费者: 消费到 3、4 号分区数据。
说明: 消费者 0 已经被踢出消费者组,所以重新按照 range 方式分配。

RoundRobin:假设topic1 有5个分区  3个消费者实例  那么会按照
0号消费者  消费0、3两个分区;
1号消费者消费1、4 两个分区;
3号消费者消费分区 2的数据。
如果0号消费者宕机 则此时触发再平衡。 0 号消费者的任务会整体被分配到 1 号消费者或者 2 号消费者。

1 号消费者: 消费到 0、2、4  号分区数据
2 号消费者: 消费到 1、3号分区数据
说明: 消费者 0 已经被踢出消费者组,所以重新按照 RoundRobin 方式分配。

Sticky :假设topic1 有5个分区  3个消费者实例 
0 号消费者: 消费到 0、2 号分区数据。
1号消费者: 消费到 1、3 号分区数据。
2 号消费者: 消费到 4 号分区数据。

如果0号消费者宕机 则此时触发再平衡。 0 号消费者的任务会整体被分配到 1 号消费者或者 2 号消费者。
1 号消费者: 消费到 0、2、3  号分区数据
2 号消费者: 消费到 2、4号分区数据
说明: 消费者 0 已经被踢出消费者组,所以重新按照 Sticky
 方式分配。

offset

  • 1)自动提交
           为了使我们能够专注于自己的业务逻辑,Kafka提供了自动提交offset的功能。 自动提交offset的相关参数:

    enable.auto.commit:是否开启自动提交offset功能,默认是true
    auto.commit.interval.ms:  自动提交offset的时间间隔,默认是5s

  • 2)手动提交
    •          虽然自动提交offset十分简单便利,但由于其是基于时间提交的,开发人员难以把握offset提交的时机。因 此Kafka还提供了手动提交offset的API。手动提交offset的方法有两种:分别是commitSync  (同步提交) 和commitAsync  (异步提交) 。两者的相 同点是,都会将本次提交的一批数据最高的偏移量提交;不同点是, 同步提交阻塞当前线程,一直到提交成功,并且会自动失败重试 (由不可控因素导致,也会出现提交失败) ;而异步提交则没有失败重试机制,有可能提交失败。 
  • 3)指定 Offset 消费

    •         ​​​​​​​auto.offset.reset = earliest | latest | none    默认是 latest。当 Kafka  中没有初始偏移量(消费者组第一次消费)或服务器上不再存在当前偏移量时

      • (1) earliest:自动将偏移量重置为最早的偏移量。
        (2) latest  (默认值): 自动将偏移量重置为最新偏移量。

        (3) none:如果未找到消费者组的先前偏移量,则向消费者抛出异常。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值