摘要
在上边我们介绍了Kafka涉及到的基本概念,消息交付语义,高可靠相关原理,现在开始向下研究一些细节设计以及源码。本文主要讲述Producer和Consumer在生产/消费时是如何确定分区的
如有问题,欢迎gitee 提 issue,共同进步
Producer 分区机制
关于分区的概念,我们在基础知识阶段就已经讲过了,不再赘述。Kafka能实现这么大吞吐量,主要就是在能够高速的写入,而在分布式系统里,为了实现这一点,就一定需要负载均衡,将集群的压力分摊到各个节点上,避免出现倾斜,导致单点。
所以,Producer的分区其实就是一个负载均衡的过程,也是Kafka实现高吞吐的基础。Kafka Producer 支持如下的分区策略
-
轮询
- 就像名字一样,轮流把消息写入到各个分区,这样能保证各个分区内的消息数量都非常节点,实现集群的平衡,也是Kafka默认的策略,没有特殊需求,不建议修改
-
随机
-
获取分区数量
-
生成随机数,指定分区的Index,然后写入
-
List partitions = cluster.partitionsForTopic(topic); return ThreadLocalRandom.current().nextInt(partitions.size());
-
-
按Key保存
- 发送消息的时候指定Key,相同的Key会计算hash值然后放到同一个分区内。
- kafka 发送消息的时候默认是轮询,如果指定了Key,则会按key存储
-
自定义分区策略
- 自己实现Partitioner.class,然后在Producer内指定分区类
以上就是Kafka自带及支持的分区策略
Consumer 分区机制
Consumer 消费分区机制是由kafka内置的,因为上传的时候的分区了,所以消费的时候也要分区。Consumer还有一个 Consumer Group 的概念。Consumer Group 是为了屏蔽Consumer 实例设计的,一个group内有多个实例,这样,某一个实例挂掉之后,能迅速且换消费实例。一个分区只能被一个消费者实例消费。
-
Range
-
range分配策略针对的是主题(PS:也就是说,这里所说的分区指的某个主题的分区,消费者值的是订阅这个主题的消费者组中的消费者实例)
-
首先,将分区按数字顺序排行序,消费者按消费者名称的字典序排好序
-
然后,用分区总数除以消费者总数。如果能够除尽,则皆大欢喜,平均分配;若除不尽,则位于排序前面的消费者将多负责一个分区
例如,假设有两个消费者C0和C1,两个主题t0和t1,并且每个主题有3个分区,分区的情况是这样的:t0p0,t0p1,t0p2,t1p0,t1p1,t1p2
那么,基于以上信息,最终消费者分配分区的情况是这样的:
C0: [t0p0, t0p1, t1p0, t1p1]
C1: [t0p2, t1p2]
-
-
轮询
- 轮询着把Topic的分区分配给所有Consumer
-
固定分配
- 即尽量不动已有的分配策略