为什么Apache Kafka只允许添加主题,但不允许删除主题中的分区。它是如何在内部工作的。它是否对分区使用哈希?
答案 0 :(得分:0)
分区实际上是通过使用murmur2哈希算法对消息密钥进行哈希处理,然后计算该个分区的模数来执行的。 这是在生产时通过生产者将消息发送给代理程序来完成的,该代理程序然后将消息存储在该分区的日志中。如果消息中没有密钥,则生产者进行循环轮询。 所有这些都是默认行为,分区程序是可插入的,因此您可以为此执行任何操作。
这也是为什么您无法在Kafka中删除分区的原因,因为这意味着数据需要重新分区然后再分发到其他分区,这有几个问题:
相比之下,添加分区相当简单,因为这只会影响新消息。基本上,当您添加分区时,生产者将在一段时间后(达到metadata.max.age.ms时刷新元数据)会注意到新分区,并将它们简单地包括在其分区方案中,无论其外观如何。
答案 1 :(得分:0)
Apache Kafka不支持减少主题的分区,因为这会导致数据丢失。此外,这也将导致分配给特定分区的键控消息出现更多问题。
默认情况下,关于您的哈希问题,Kafka利用DefaultPartitioner
(org.apache.kafka.clients.producer.internals.DefaultPartitioner
)跨主题分区分发消息:
/**
* Compute the partition for the given record.
*
* @param topic The topic name
* @param key The key to partition on (or null if no key)
* @param keyBytes serialized key to partition on (or null if no key)
* @param value The value to partition on or null
* @param valueBytes serialized value to partition on or null
* @param cluster The current cluster metadata
*/
public int partition(String topic, Object key, byte[] keyBytes, Object value, byte[] valueBytes, Cluster cluster) {
if (keyBytes == null) {
return stickyPartitionCache.partition(topic, cluster);
}
List<PartitionInfo> partitions = cluster.partitionsForTopic(topic);
int numPartitions = partitions.size();
// hash the keyBytes to choose a partition
return Utils.toPositive(Utils.murmur2(keyBytes)) % numPartitions;
}
本质上,DefaultPartitioner
使用 MurmurHash ,这是一种非加密的哈希函数,通常用于基于哈希的查找。然后,将此散列用于模运算(% numPartitions
)中,以确保返回的分区在[0, N]
范围内,其中N
是主题的分区数。
解决方法
假设您仍然想减少一个主题的分区数,您仍然可以创建一个分区更少的新分区,然后将消息从旧主题复制到新创建的主题。这样,您将能够将密钥消息分发到正确的分区。