kafka允许向主题添加分区,但不能删除?

时间:2019-10-07 08:27:52

标签: hash apache-kafka partitioning

为什么Apache Kafka只允许添加主题,但不允许删除主题中的分区。它是如何在内部工作的。它是否对分区使用哈希?

2 个答案:

答案 0 :(得分:0)

分区实际上是通过使用murmur2哈希算法对消息密钥进行哈希处理,然后计算该个分区的模数来执行的。 这是在生产时通过生产者将消息发送给代理程序来完成的,该代理程序然后将消息存储在该分区的日志中。如果消息中没有密钥,则生产者进行循环轮询。 所有这些都是默认行为,分区程序是可插入的,因此您可以为此执行任何操作。

这也是为什么您无法在Kafka中删除分区的原因,因为这意味着数据需要重新分区然后再分发到其他分区,这有几个问题:

  • 经纪人不知道写消息时生产者如何选择分区
  • 消息现在已经很旧了,需要在经纪人日志中的较早位置插入,由于Kafka的偏移量呈线性上升,因此这是不可能的

相比之下,添加分区相当简单,因为这只会影响新消息。基本上,当您添加分区时,生产者将在一段时间后(达到metadata.max.age.ms时刷新元数据)会注意到新分区,并将它们简单地包括在其分区方案中,无论其外观如何。

答案 1 :(得分:0)

Apache Kafka不支持减少主题的分区,因为这会导致数据丢失。此外,这也将导致分配给特定分区的键控消息出现更多问题。

默认情况下,关于您的哈希问题,Kafka利用DefaultPartitionerorg.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是主题的分区数。

解决方法

假设您仍然想减少一个主题的分区数,您仍然可以创建一个分区更少的新分区,然后将消息从旧主题复制到新创建的主题。这样,您将能够将密钥消息分发到正确的分区。