Kafka分区、副本机制(二)

本文详细介绍了Kafka的分区和副本机制,包括轮询、随机和按key分区策略,以及如何保证消息消费顺序。此外,还讨论了消费者组的再平衡机制、消费者分区分配策略,以及producer的ACKs参数对消息可靠性的影响。

2.Kafka 高级

2.1. 分区和副本机制

2.1.1 分区写入策略

生产者可以写入消息到同批次中,Kafka将会根据不同的策略分配到不同的分区中。

分区策略主要3种:

  1. 轮询分区策略

    • 这是一种默认的策略,也是采用最多的策略。它可以最大限度保证所有的消息平均分配到一个分区中。

    • 当生产者生产消息时,将key设置为 null, 则认为使用轮询算法均匀地分配分区。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-yKkRTPXS-1604475558866)(…/…/AppData/Roaming/Typora/typora-user-images/image-20201101143240188.png)]

  1. 随机分区策略

    每次都将消息随机分配到不同的分区中,在较早的版本这,这是默认的分配策略。

  2. 按key分区分配策略

    按key分配策略,可能会出现 数据倾斜 。 例如:某个key包含了大量的数据,因为 key 值一样,所有的数据将分配到一个分区中,造成该分区的消息数量远大于其它的分区。

    这种方式类似于 HashMap 的思想,对key进行hashcode运算,得到的结果再进行取余,然后分配到不同的分区中。

2.1.2 Kafka 如何保证消息的消费顺序有序性?

轮询策略、随机策略都会导致一个问题,生产者生产到Kafka中的数据是乱序存储的。而按key分区分配策略可以在一定程度上实现数据的有序性,但也是局部有序性,且会导致数据倾斜,所以在实际生产环境中要结合实际情况进行取舍。

image-20201102200810504

因为 Kafka中存在者多个分区的原因,生产者生产消息时,会将数据根据分区写入策略写入到分区中,而一个消费者组中的一个消费者只能同时消费一个分区的数据,因此导致在多分区时,Kafka消费者消费的消息时全局无序的。

  • 解决办法:

    1. 如果我们要实现消息总是有序的,那么我们可以将消息连续的放入到一个partition分区中,但这种做法并不符合Kafka的设计思想

    2. (推荐)Kafka在发送 1条消息的时候,可以指定 topic,partition,key,data(数据) 4个参数。如果你发送消息的时候指定了 Partition 的话,所有消息都被发送到指定的 Partition。并且,同一个key的消息可以保证只发送到同一个partition,这样我们就可以对 表/对象的id作为key。

      因为很多的实际场景中,往往并不需要确保topic的消费完全有序。

      当然,如果场景需要保证顺序有序性,比如发送两个消息,对应数据库中的操作为更改用户会员等级和根据用户会员等级计算订单支付价格。那儿我们只需要保证key值相同的topic被顺序消费,因此,我只要将相同的key发送至相同的partition中即可。这样相比于将所有的key都发送到同一个partition,有效的利用了多个partition,从而可以被多个节点消费,实现负载均衡。

      image-20201102203410290

2.2 消费者组 Consumer Group Reblannce 机制

  • 再均衡机制:在某些情况下,消费者组中的消费者消费的分区会产生变化,会导致消费者分配不均匀(例如:有两个消费者消费3个分区,即一个消费者(C1)消费两个分区、另一个消费者(C2)消费一个分区。而恰好此时C2消费的分区崩溃了,只剩余两个分区,且恰恰都是C1消费的两个分区,所以C2消费者没有分区,就要进行削峰)Kafka Consumer Group 就会启动 rebalance机制,重新平衡Consumer Group 内的消费者消费的分区分配。

  • 触发时机:

    • 消费者数量发生变化
      • 某个消费者 crash,即消费者宕机
      • 新增消费者
    • topic的数量发生变化
      • 某个topic 被删除
    • partition的数量发生变化
      • 删除partition
      • 新增partition
  • 不良影响

    • 发生rebalance时,所有的consumer都将不再工作,共同参与再均衡,直到每个消费者都已经被成功分配所需要消费的分区位置,即rebalance结束。

2.3 消费者分区分配策略

当触发再均衡机制时,就会需要考虑怎么对分区进行分配。分区分配策略保障了每个消费者尽量能够均匀地消费分区地数据,不能出现某个消费者消费的分区特别少,某个消费者消费的分区特别多。

Kafka提供的分区分配策略主要有以下三种:

  • Range分配策略(范围分配策略):Kafka的默认分配策略

    • n: 分区数/消费者数

    • m:分区数%消费者数

    • 前m个消费者 消费 n+1 个分区

    • 剩下的消费者 消费 n 个分区

    • 假如有10个分区,3个消费者,把分区按照序号排列0,1,2,3,4,5,6,7,8,9;消费者为C1,C2,C3,那么用分区数除以消费者数来决定每个Consumer消费几个Partition,除不尽的前面几个消费者将会多消费一个
      最后分配结果如下

      C1:0,1,2,3
      C2:4,5,6
      C3:7,8,9

      如果有11个分区将会是:

      C1:0,1,2,3
      C2:4,5,6,7
      C3:8,9,10

      假如我们有两个主题T1,T2,分别有10个分区,最后的分配结果将会是这样:

      C1:T1(0,1,2,3) T2(0,1,2,3)
      C2:T1(4,5,6) T2(4,5,6)
      C3:T1(7,8,9) T2(7,8,9)

      在这种情况下,C1多消费了两个分区

    • 显然这种方式会存在有弊端的

  • RoundRobin 分配策略(轮询分配策略)

    • 消费者挨个分配消费的分区
    • 这种方式分配最均匀,但是会上下文切换明显
  • Striky 粘性分配策略

    • 在没有发生rebalance跟轮询分配策略是一致的
    • 发生rebalance,轮询分配策略会重新走一遍轮询分配的过程。而粘性会保证跟上一次尽量一致,只是将新的需要分配的分区,均匀的分配到现有可用的消费者中即可。
    • 减少上下文切换。

2.4 producer 的ACKs参数

在配置文件中,我们可以配置acks参数,即

spring.kafka.producer.acks=

properties中的acks参数表示生产者生产消息的时候,写入副本的要求严格程度。它决定了生产者的性能和可靠性中如何做取舍。

  • acks=0 性能是最好的,它不需要等待broker的确认,直接发送下一条数据,但是可能存在数据丢失的问题。
  • acks=1 等待leader副本确认接收后,才能发送下一条数据,性能中等。
  • acks=-1或all 等待所有副本已经将数据同步后才会发送下一条数据,性能最慢。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值