在 Kafka 中设计消息密钥的最佳方法是什么?
What's the best way to design message key in Kafka?
我有一个分区主题,它有 X
个分区。
截至目前,在生成消息时,我创建 Kafka 的 ProducerRecord
仅指定 topic
和 value
。我没有定义key
。
据我了解,我的消息将使用默认的内置分区程序在分区之间均匀分布。
另一方面,我有一个 Kafka 消费者线程池。每个 Kafka 消费者将 运行 在自己的专用线程中消费来自主题的消息。这些消费者中的每一个都被赋予了相同的 group.id
。这将允许并行使用消息。每个消费者都将分配到其公平份额的分区以供读取。
我希望以有序的方式使用我的消息。我知道 Kafka 保证分区内消息的顺序。所以,只要我想出一个合适的密钥结构,我就会对我的消息进行分区,使它们最终位于同一个分区中。在某种程度上,消息键将消息分组并存储在分区中。
有道理吗?
问:是否有可能由于密钥设计不当导致分区不均匀?一个人可能会收到比其他人更多的记录。它会对我的 Kafka 集群的性能产生不良影响吗?消息键设计的最佳实践是什么?
Kafka 将在密钥上应用 murmur 散列并与分区数取模,因此它即 murmur2(record.key())) % num partitions。在所有可能的情况下,它应该在默认分区的情况下均匀分布。我建议您使用 java 中编写的简单 murmur2 函数来试验所有关键选项,以查看分布模式,然后做出选择。
kafka 中也有两种默认分区的实现。 Murmur 哈希实现在较新的版本中。旧旧版本的工作方式不同。
您对默认分区程序的理解是正确的。
如果您不需要按照生成消息的顺序使用某些消息,那么不指定密钥是最佳选择。如果这不是您的情况,那么您的要求会告诉您什么必须是您的密钥。例如,如果您想为给定用户保留生成消息的顺序,user_id 可能是您的消息密钥。
要实现特定的消息顺序,您需要考虑生产者的配置方式。如果您的生产者可以在失败的情况下重试发送消息并且 in flight messages
高于 1,则可以乱序生产消息。
您可以通过指定错误的密钥来获得不均匀的分区。例如,如果您 90% 的用户来自纽约,10% 来自其他城市,并且您选择一个城市作为键,那么您的一个分区将非常庞大,并且其中一个消费者超载(我假设消息的数量每个用户是相同的)。
我有一个分区主题,它有 X
个分区。
截至目前,在生成消息时,我创建 Kafka 的 ProducerRecord
仅指定 topic
和 value
。我没有定义key
。
据我了解,我的消息将使用默认的内置分区程序在分区之间均匀分布。
另一方面,我有一个 Kafka 消费者线程池。每个 Kafka 消费者将 运行 在自己的专用线程中消费来自主题的消息。这些消费者中的每一个都被赋予了相同的 group.id
。这将允许并行使用消息。每个消费者都将分配到其公平份额的分区以供读取。
我希望以有序的方式使用我的消息。我知道 Kafka 保证分区内消息的顺序。所以,只要我想出一个合适的密钥结构,我就会对我的消息进行分区,使它们最终位于同一个分区中。在某种程度上,消息键将消息分组并存储在分区中。
有道理吗?
问:是否有可能由于密钥设计不当导致分区不均匀?一个人可能会收到比其他人更多的记录。它会对我的 Kafka 集群的性能产生不良影响吗?消息键设计的最佳实践是什么?
Kafka 将在密钥上应用 murmur 散列并与分区数取模,因此它即 murmur2(record.key())) % num partitions。在所有可能的情况下,它应该在默认分区的情况下均匀分布。我建议您使用 java 中编写的简单 murmur2 函数来试验所有关键选项,以查看分布模式,然后做出选择。 kafka 中也有两种默认分区的实现。 Murmur 哈希实现在较新的版本中。旧旧版本的工作方式不同。
您对默认分区程序的理解是正确的。
如果您不需要按照生成消息的顺序使用某些消息,那么不指定密钥是最佳选择。如果这不是您的情况,那么您的要求会告诉您什么必须是您的密钥。例如,如果您想为给定用户保留生成消息的顺序,user_id 可能是您的消息密钥。
要实现特定的消息顺序,您需要考虑生产者的配置方式。如果您的生产者可以在失败的情况下重试发送消息并且 in flight messages
高于 1,则可以乱序生产消息。
您可以通过指定错误的密钥来获得不均匀的分区。例如,如果您 90% 的用户来自纽约,10% 来自其他城市,并且您选择一个城市作为键,那么您的一个分区将非常庞大,并且其中一个消费者超载(我假设消息的数量每个用户是相同的)。