kafka如何平衡分区负载?
How kafka balances partitions load?
我遇到了一个关于 kafka 负载均衡的问题。因此,我创建了一个包含 10 个分区的主题并创建了 2 个消费者。 10 个分区被划分并分配给这些消费者(5 个分区分配给第一个,5 个分区分配给第二个)并且工作正常。有时第一个消费者工作,有时第二个。
但有时我们会遇到这样的情况,例如第二个消费者收到一条消息,并且需要时间(例如 10 分钟)来处理这条消息。
所以,我的问题是kafka将如何决定将消息存储到哪个分区?
我认为这种情况下的循环法不是一个好主意,因为由第二个消费者处理的分区中的消息在第二个消费者完成漫长的工作之前不会被处理。
已更新!
根据@Milan Baran 的回答,生产者端的负载是平衡的。但是在这种情况下,即使我们提供了一个自定义的 Partitioner
实现,同样的问题是存储在分配给长期工作的消费者的分区中的消息不会被删除。处理直到该消费者完成其长期工作。
可能是,其他地方有额外的负载均衡器?
使用哪个partition不由kafka决定,而是由发送消息的producer决定。看看https://kafka.apache.org/documentation#producerconfigs
您可以提供分区程序 class 来决定选择哪个分区。
partitioner.class
Partitioner class that implements the Partitioner
interface. org.apache.kafka.clients.producer.internals.DefaultPartitioner
有 DefaultPartitioner 策略的描述
/**
* The default partitioning strategy:
* <ul>
* <li>If a partition is specified in the record, use it
* <li>If no partition is specified but a key is present choose a partition based on a hash of the key
* <li>If no partition or key is present choose a partition in a round-robin fashion
*/
看来你需要的是一个QUEUE。 ONE 分区被 MULTIPLE 消费者使用。每个消费者从分区中获取一条记录,处理它,然后获取另一条记录。如果一个消费者花费太多时间来处理记录,其他消费者仍然可以从分区中获取(不同的)记录。
但是,Kafka 不 支持这一点。每个分区只能被消费组中的一个消费者消费。
总之,你需要别的东西来达到目的,比如RabbitMQ。
感谢大家的帮助。但我找到了我的问题的答案。所以首先,kafka至少有3处负载均衡:
- 将分区分配给消费者 "Round robin" 或 "Range"
使用算法。这可以通过设置
partition.assignment.strategy
属性。默认使用范围。
- 在生产者级别可以应用选择分区的策略
存储消息。可以通过
partitioner.class
来完成
- 以及我的问题的答案。如果一个消费者处理消息
很长一段时间,卡夫卡认为这个消费者已经死了,
在另一个消费者之间重新分配分区。所以当很长一段时间
工作由消费者完成,没有分配给它的分区。什么时候
消费者完成长时间的工作分区将被分配给
再次。并且不会有待处理的消息。
我遇到了一个关于 kafka 负载均衡的问题。因此,我创建了一个包含 10 个分区的主题并创建了 2 个消费者。 10 个分区被划分并分配给这些消费者(5 个分区分配给第一个,5 个分区分配给第二个)并且工作正常。有时第一个消费者工作,有时第二个。
但有时我们会遇到这样的情况,例如第二个消费者收到一条消息,并且需要时间(例如 10 分钟)来处理这条消息。
所以,我的问题是kafka将如何决定将消息存储到哪个分区?
我认为这种情况下的循环法不是一个好主意,因为由第二个消费者处理的分区中的消息在第二个消费者完成漫长的工作之前不会被处理。
已更新!
根据@Milan Baran 的回答,生产者端的负载是平衡的。但是在这种情况下,即使我们提供了一个自定义的 Partitioner
实现,同样的问题是存储在分配给长期工作的消费者的分区中的消息不会被删除。处理直到该消费者完成其长期工作。
可能是,其他地方有额外的负载均衡器?
使用哪个partition不由kafka决定,而是由发送消息的producer决定。看看https://kafka.apache.org/documentation#producerconfigs
您可以提供分区程序 class 来决定选择哪个分区。
partitioner.class
Partitioner class that implements the Partitioner interface. org.apache.kafka.clients.producer.internals.DefaultPartitioner
有 DefaultPartitioner 策略的描述
/**
* The default partitioning strategy:
* <ul>
* <li>If a partition is specified in the record, use it
* <li>If no partition is specified but a key is present choose a partition based on a hash of the key
* <li>If no partition or key is present choose a partition in a round-robin fashion
*/
看来你需要的是一个QUEUE。 ONE 分区被 MULTIPLE 消费者使用。每个消费者从分区中获取一条记录,处理它,然后获取另一条记录。如果一个消费者花费太多时间来处理记录,其他消费者仍然可以从分区中获取(不同的)记录。
但是,Kafka 不 支持这一点。每个分区只能被消费组中的一个消费者消费。
总之,你需要别的东西来达到目的,比如RabbitMQ。
感谢大家的帮助。但我找到了我的问题的答案。所以首先,kafka至少有3处负载均衡:
- 将分区分配给消费者 "Round robin" 或 "Range"
使用算法。这可以通过设置
partition.assignment.strategy
属性。默认使用范围。 - 在生产者级别可以应用选择分区的策略
存储消息。可以通过
partitioner.class
来完成
- 以及我的问题的答案。如果一个消费者处理消息 很长一段时间,卡夫卡认为这个消费者已经死了, 在另一个消费者之间重新分配分区。所以当很长一段时间 工作由消费者完成,没有分配给它的分区。什么时候 消费者完成长时间的工作分区将被分配给 再次。并且不会有待处理的消息。