我有一个主题有10个分区,1个消费者群体有4个消费者,工人大小是3。
我可以看到分区中的消息分布不均匀,一个分区拥有如此多的数据而另一个分区是免费的。
如何让我的生产者将负载均匀地分配到所有分区,以便正确使用所有分区?
答案 0 :(得分:1)
似乎你的问题是消息的消费不均衡而不是向Kafka主题产生不均匀的消息。换句话说,您的读取线程数量与您拥有的分区数量不匹配(它们不需要匹配1:1,但每个消费者线程只能读取相同数量的分区)。
See简短说明了解更多细节。
答案 1 :(得分:1)
您可以使用生产者记录的关键参数。以下是对于特定键,数据现在始终进入同一分区的事情,我不知道生产者记录的结构,但正如您所说的那样,您有10个分区,那么您可以使用n%10作为生产者记录密钥。 其中n为0到9,现在你的记录0键将为0然后kafka将生成一个哈希键并将其放入某个分区,例如分区0,对于记录1,它将为1,然后它将进入第一个分区等等。 通过这种方式,您可以在生产者记录中应用循环,您的密钥将独立于记录中的字段,因此您可以将变量n和密钥设置为n%10。
或者您可以在生产者记录中指定分区。因此,要么使用生产者记录的密钥或分区字段。
答案 2 :(得分:1)
您可以为生产者分配一个分区号,而不是使用默认的分区器类,这样消息就可以直接转到指定的分区,
ProducerRecord<String, String> record = new ProducerRecord<String, String>(topicName, partitionNumber,key, value);
答案 3 :(得分:0)
根据DefaultPartitioner类本身的JavaDoc注释,默认的分区策略是:
因此,可能导致分布不均的两个可能原因取决于您是否在生成消息时指定密钥:
如果您正在使用DefaultPartitioner指定密钥并且获得的分布不均匀,则最明显的解释是您多次指定相同的密钥。
如果您没有指定密钥并使用DefaultPartitioner,则可能会发生非显而易见的行为。根据以上所述,您可能会期望循环分发消息,但情况并非如此。 0.8.0中引入的优化可能导致使用相同的分区。请查看此链接以获取更详细的说明:https://cwiki.apache.org/confluence/display/KAFKA/FAQ#FAQ-Whyisdatanotevenlydistributedamongpartitionswhenapartitioningkeyisnotspecified?。
答案 4 :(得分:0)
如果您已经从记录中定义了分区程序,那么在Kafka中,键是字符串,值是学生Pojo。
在Pojo学生中,根据学生所在的国家/地区,我想进入特定的分区。想象一下,一个主题中有10个分区,例如,在值上,“印度”是一个国家,根据“印度”,我们得到了分区号5。
无论国家/地区是“印度”,Kafka都会分配5号分区,并且该记录将始终分配到5号分区(如果分区未更改)。
让我们说,在您的管道中,有很多记录即将到来,并且有一个国家“印度”,所有这些记录都将进入5号分区,并且您会看到Kafka分区中的分布不均。
答案 5 :(得分:0)
就我而言,我使用默认分区程序,但一个分区中的记录仍然比其他分区多得多。问题是我出乎意料的是,许多记录具有相同的键。检查您的钥匙!
答案 6 :(得分:0)
由于我无法使用Faust解决此问题,因此我使用的方法是自己实施“循环”分发。
我遍历我的记录以生成并执行例如:
for index, message in enumerate(messages):
topic.send(message, partition=index % num_partitions)
即将索引绑定到我拥有的分区范围内。
仍然可能存在不均匀性-考虑到您反复运行此操作,但是记录数少于num_partitions
-那么第一个分区将继续获得大部分消息。您可以通过添加随机偏移量来避免此问题:
import random
initial_partition = random.randrange(0, num_partitions)
for index, message in enumerate(messages):
topic.send(message, partition=(initial_partition + index) % num_partitions)