默认的 Kafka 分区器创建哈希键冲突

Posted

技术标签:

【中文标题】默认的 Kafka 分区器创建哈希键冲突【英文标题】:The default Kafka partitioner create hash key collision 【发布时间】:2019-05-31 19:26:15 【问题描述】:

我有一个包含 10 个分区的主题,并且我使用 A,B,C,D,E,F,G,H,I 9 个不同的键生成事件。

我观察到有这样的消息:

Partition 0- (Message1, Key E), (Message2, Key I)
Partition 1- (Message3, Key F) 
. 
. 
Partition7-(Message4, Key A), (Message5, Key A)
Partition8- Empty 
Partition9- Empty

同一个分区有2条不同key的消息,也有空分区。

Kafka 的默认partitioner 是否会造成冲突?

我正在从一个平衡到两个默认休息producers 的流进行生产。

这是我所期待的:

 Partition 0- (Message1, Key E)
 Partition 1- (Message3, Key F) 
 . 
 . 
 Partition7-(Message4, Key A), (Message5, Key A)
 Partition8-(Message2, Key I) 
 Partition9- Empty

【问题讨论】:

【参考方案1】:

Kafka 的 DefaultPartitioner 在生产者客户端使用murmur 哈希算法为每条消息分配一个分区。不能保证对于 10 个分区和个位数的键,它们会均匀分布。每个消息的分区计算是相互独立的,碰撞概率是一个数学兴趣。

编辑:

杂音哈希算法导致冲突的可能性很小。 Kafka 主题中的分区是固定的 - 它不会像 java HashMap 实现中的桶大小一样增长。因此,分区算法使用计算分区数模的公式。确切的公式是Utils.toPositive(Utils.murmur2(keyBytes)) % numPartitions;

现在您可以看到,如果hash mod number of partitions 产生相同的值,则两个不同的键确实可以产生相同的分区号。

对于大量随机密钥集,密钥将均匀分布在所有分区中。

如果您想要排序,那么您必须使用分区键..在这种情况下,您对冲突和空分区的担忧几乎没有实际后果(好吧,对于大量随机键来说,它们是可以的)。 如果您假设 Kafka 会集中确保在将密钥路由到已填充的分区之前先填充空分区,那么事情就不是这样了

【讨论】:

产生冲突的哈希的目的是什么?有什么指南可以选择不让它们碰撞的键吗? @Dipperman,根据定义,哈希应该会产生冲突 (en.wikipedia.org/wiki/Hash_function) @wardziniak 我知道根据定义散列会产生冲突,但我不明白为什么我们需要在 Kafka 中发生冲突?没有碰撞会均匀分布。 如果要均匀分布,省略key,默认partitioner会使用round-robin进行分区 在这种情况下,我将统一但无序。我需要订购有关其键的事件【参考方案2】:

是的,默认分区程序会产生冲突,最迟当您拥有的密钥比您拥有的分区多一个时才会发生冲突。请参阅@senseiwu 的答案,它很好地解释了会发生什么。 如果您有一组有限的键并希望将它们分布在相同数量的分区上,您必须实现自己的分区器。

【讨论】:

以上是关于默认的 Kafka 分区器创建哈希键冲突的主要内容,如果未能解决你的问题,请参考以下文章

Kafka生产者

kafka总结

如果在 Hadoop Map Reduce 中定义了自定义分区器,默认哈希分区器是不是仍然有效?

kafka3-核心概念

2、kafka如何选定分区数量

09 APACHE KAFKA原理