生产者消息分区机制原理剖析
为什么分区?
- Kafka 有主题(Topic)的概念,它是承载真实数据的逻辑容器,而在主题之下还分为若干个分区,也就是说 Kafka 的消息组织方式实际上是三级结构:主题 - 分区 - 消息。
- 主题下的每条消息只会保存在某一个分区中,而不会在多个分区中被保存多份。
- 分区的作用就是提供负载均衡的能力
- 对数据进行分区的主要原因,就是为了实现系统的高伸缩性(Scalability)。
- 不同的分区能够被放置到不同节点的机器上,而数据的读写操作也都是针对分区这个粒度而进行的,这样每个节点的机器都能独立地执行各自分区的读写请求处理。
- 并且,我们还可以通过添加新的节点机器来增加整体系统的吞吐量。
- 除了提供负载均衡这种最核心的功能之外,利用分区也可以实现其他一些业务级别的需求,比如实现业务级别的消息顺序的问题。
- 不同的分布式系统对分区的叫法也不尽相同。
- 在 Kafka 中叫分区;
- 在 MongoDB 和 Elasticsearch 中就叫分片 Shard;
- 在 HBase 中则叫 Region;
- 在 Cassandra 中被称作 vnode。
都有哪些分区策略?
- 如果要自定义分区策略,你需要显式地配置生产者端的参数 partitioner.class。
- 在编写生产者程序时,你可以编写⼀个具体的类实现 org.apache.kafka.clients.producer.Partitioner 接口。
- 这个接口也很简单,只定义了两个方法:partition() 和 close(),通常你只需要实现最重要的 partition 方法。
- 所谓分区策略是决定生产者将消息发送到哪个分区的算法。
轮询策略
- Round-robin 策略,即顺序分配:
- 轮询策略是 Kafka Java 生产者 API 默认提供的分区策略。
- 轮询策略有非常优秀的负载均衡表现,它总是能保证消息最大限度地被平均分配到所有分区上,故默认情况下它是最合理的分区策略,也是我们最常用的分区策略之一。
随机策略
- 所谓随机就是我们随意地将消息放置到任意一个分区上。
- Randomness 策略:
- 本质上看随机策略也是力求将数据均匀地打散到各个分区,但从实际表现来看,它要逊于轮询策略,所以如果追求数据的均匀分布,还是使用轮询策略比较好。
按消息键保序策略
- Kafka 允许为每条消息定义消息键,简称为 Key。
- 一旦消息被定义了 Key,那么你就可以保证同一个 Key 的所有消息都进入到相同的分区里面,由于每个分区下的消息处理都是有顺序的,故这个策略被称为按消息键保序策略:
- 实现这个策略的 partition 方法只需要两行代码即可:
List<PartitionInfo> partitions = cluster.partitionsForTopic(topic); return Math.abs(key.hashCode()) % partitions.size();
- Kafka 默认分区策略实际上同时实现了两种策略:如果指定了 Key,那么默认实
现按消息键保序策略;如果没有指定 Key,则使用轮询策略。