在介绍kafka的分区策略之前,先看看几个简单的概念
1.topic
在 kafka 中,topic 是一个存储消息的逻辑概念,可以认为是一个消息集合。每条消息发送到 kafka 集群的消息都有一个类别。物理上来说,不同的 topic 的消息是分开存储的,每个 topic 可以有多个生产者向它发送消息,也可以有多个消费者去消费其中的消息
2.partition
每个 topic 可以划分多个分区(每个 Topic 至少有一个分区),同一 topic 下的不同分区包含的消息是不同的。每个消息在被添加到分区时,都会被分配一个 offset(称之为偏移量),它是消息在此分区中的唯一编号,kafka 通过 offset保证消息在分区内的顺序,offset 的顺序不跨分区,即 kafka只保证在同一个分区内的消息是有序的。
下图中,对于名字为 test 的 topic,做了 3 个分区,分别是p0、p1、p2
每一条消息发送到 broker 时,会根据 partition 的规则选择存储到哪一个 partition。如果 partition 规则设置合理,那么所有的消息会均匀的分布在不同的partition中,这样就有点类似数据库的分库分表的概念,把数据做了分片处理
3.Topic&Partition 的存储
Partition 是以文件的形式存储在文件系统中,比如创建一个名为 firstTopic 的 topic,其中有 3 个 partition,那么在kafka 的数据目录(/tmp/kafka-log)中就有 3 个目录,
firstTopic-0~3,命名规则是<topic_name>-<partition_id>
命令如下:
bin/kafka-topics.sh --zookeeper 192.168.44.129:2181 --replication-factor 1 --partitions 3 --create --topic firstTopic
4. 消息分发
kafka 消息分发策略
消息是 kafka 中最基本的数据单元,在 kafka 中,一条消息由 key、value 两部分构成,在发送一条消息时,我们可以指定这个 key,那么 producer 会根据 key 和 partition 机制来判断当前这条消息应该发送并存储到哪个 partition 中。我们可以根据需要进行扩展 producer 的 partition 机制
消息默认的分发机制
默认情况下,kafka 采用的是hash 取模的分区算法
。如果Key 为 null,则会随机分配一个分区
。这个随机是在这个producer配置参数”metadata.max.age.ms”的时间范围内随机选择一个。metadata.max.age.ms表示的是用于配置每个producer端缓存topic的metadata的过期时间,默认值为5分钟,对于这个时间段内,如果 key 为 null,则只会发送到唯一的分区。这默认情况下是 5 分钟更新一次。
关 于 Metadata ,简单理解就是Topic/Partition 和 broker 的映射关系,每一个 topic 的每一个 partition,需要知道对应的 broker 列表是什么,leader是谁、follower 是谁。这些信息都是存储在 Metadata 这个类里面。
消费端如何消费指定的分区
通过下面的代码,就可以消费指定该 topic 下的 0 号分区。其他分区的数据就无法接收
kafkaConsumer=new KafkaConsumer(properties);
// kafkaConsumer.subscribe(Collections.singletonList(topic));
//消费指定分区
TopicPartition topicPartition=new TopicPartition(topic,0);
kafkaConsumer.assign(Arrays.asList(topicPartition));