kafka-specific-partition

55 阅读3分钟

摘要

在上边我们介绍了Kafka涉及到的基本概念,消息交付语义,高可靠相关原理,现在开始向下研究一些细节设计以及源码。本文主要讲述Producer和Consumer在生产/消费时是如何确定分区

如有问题,欢迎gitee 提 issue,共同进步

Producer 分区机制

关于分区的概念,我们在基础知识阶段就已经讲过了,不再赘述。Kafka能实现这么大吞吐量,主要就是在能够高速的写入,而在分布式系统里,为了实现这一点,就一定需要负载均衡,将集群的压力分摊到各个节点上,避免出现倾斜,导致单点。

所以,Producer的分区其实就是一个负载均衡的过程,也是Kafka实现高吞吐的基础。Kafka Producer 支持如下的分区策略

  1. 轮询

    1. 就像名字一样,轮流把消息写入到各个分区,这样能保证各个分区内的消息数量都非常节点,实现集群的平衡,也是Kafka默认的策略,没有特殊需求,不建议修改
  2. 随机

    1. 获取分区数量

    2. 生成随机数,指定分区的Index,然后写入

    3. List partitions = cluster.partitionsForTopic(topic);
      return ThreadLocalRandom.current().nextInt(partitions.size());
      
  3. 按Key保存

    1. 发送消息的时候指定Key,相同的Key会计算hash值然后放到同一个分区内。
    2. kafka 发送消息的时候默认是轮询,如果指定了Key,则会按key存储
  4. 自定义分区策略

    1. 自己实现Partitioner.class,然后在Producer内指定分区类

以上就是Kafka自带及支持的分区策略

Consumer 分区机制

Consumer 消费分区机制是由kafka内置的,因为上传的时候的分区了,所以消费的时候也要分区。Consumer还有一个 Consumer Group 的概念。Consumer Group 是为了屏蔽Consumer 实例设计的,一个group内有多个实例,这样,某一个实例挂掉之后,能迅速且换消费实例。一个分区只能被一个消费者实例消费。

  1. Range

    1. range分配策略针对的是主题(PS:也就是说,这里所说的分区指的某个主题的分区,消费者值的是订阅这个主题的消费者组中的消费者实例)

    2. 首先,将分区按数字顺序排行序,消费者按消费者名称的字典序排好序

    3. 然后,用分区总数除以消费者总数。如果能够除尽,则皆大欢喜,平均分配;若除不尽,则位于排序前面的消费者将多负责一个分区

    例如,假设有两个消费者C0和C1,两个主题t0和t1,并且每个主题有3个分区,分区的情况是这样的:t0p0,t0p1,t0p2,t1p0,t1p1,t1p2

    那么,基于以上信息,最终消费者分配分区的情况是这样的:

    C0: [t0p0, t0p1, t1p0, t1p1]

    C1: [t0p2, t1p2]

  2. 轮询

    1. 轮询着把Topic的分区分配给所有Consumer
  3. 固定分配

    1. 即尽量不动已有的分配策略