Kafka主题和微服务的多个实例

4

这更像是一个系统设计问题。

假设我有一个微服务架构,并且我有X个实例Service B(用于负载均衡HTTP请求到该服务)。但是,Service B也是某个Kafka主题的消费者。如何避免处理相同的消息X次(X是Service B的实例数)?如果处理是幂等的,那么“至少一次”可能是可以接受的。它不需要是“确切一次”,但不能是“X次”。

服务A可以是订单服务。它会向Orders topic发送关于用户下订单的消息。

服务B可以是支付服务。它从Orders topic消费消息以向用户收费。

为订单付款可能是一个幂等操作。但即使如此,如果我有10个支付服务实例,我也不想浪费CPU和IO来执行10次相同的操作。

即使分区是答案,如果我们比分区还有更多的特定微服务实例怎么办?

2个回答

7

Kafka消费者组

当您有一个服务的x个实例,并且希望消息仅被服务消费一次时,这就是Kafka的消费者组 概念所处理的。

基本上,您需要为服务实例指定一个共同的Kafka消费者组ID,然后Kafka将负责将主题的分区分配给不同的服务消费者实例,以便服务不会多次消费任何消息。

在您使用的Kafka消费者库的Kafka消费者配置中,会有一个与消费者组ID相关的配置。您只需确保单个服务实例组被分配相同的消费者组ID值即可。

通过示例进行解释

如果您的服务B10个实例,则为所有10个实例指定一个共同的Kafka消费者组ID,例如serviceBConsumerGroup。当从具有10个分区的Kafka主题进行消费时,Kafka会将主题的分区分配给消费者组serviceBConsumerGroup的所有实例。因此,它会将每个分区分配给每个实例(当服务有10个实例和主题有10个分区时)。 如果服务有5个实例并且Kafka主题有10个分区,则Kafka将为每个实例分配2个分区进行消费。

一些有关Kafka消费者组的参考资料:


1
当您有x个服务实例,并且希望消息仅被服务消费一次时,这是Kafka的消费者组概念所关注的事情。-- 这不是真的。即使您有x个实例和一个消费者,那么也不会再处理任何消息,因为它基于消费者偏移量工作。在处理完消息后,消费者会提交该消息的偏移量,以便该消息不会再次被处理。而问题是关于重新处理消息而不是并行处理消息。 - Vaibs
Kafka消费者始终在消费者偏移量上工作,以跟踪消费者组已经消费的消息。如果有x个服务实例,它们都具有唯一的消费者组,则该主题的消息可以被服务消费x次。OP的问题是“如何避免多次处理相同的消息”,这就是将相同的消费者组分配给所有实例所实现的目的。 - Madhu Bhat
我认为这与你所说的完全相反。如果我有10个消费者属于一个唯一的单个消费者组,消息再次被处理,那么消费者组有什么用处?据我所知,每个消费者组都带有唯一的ID。当我们添加并行性或其他消费者想要对该主题数据执行其他操作时,消费者组才会出现在画面中。例如,消费者A对订单数据进行计算,而消费者B根据订单数据发送通知。请查看此博客https://dzone.com/articles/kafka-consumer-architecture-consumer-groups-and-su.. - Vaibs
如果您有任何疑惑,请查看我在答案中添加的参考资料。 - Madhu Bhat
一个消费者组ID对应一个消费者组。消费者组中有多少个实例取决于分配给每个服务(Kafka消费者)实例的消费者组ID。如果x个服务实例具有共同的消费者组ID,则主题中的消息仅由服务实例集合消耗一次。如果x个服务实例具有唯一的消费者组ID,则主题中的消息将被服务实例集合消耗x次(基本上是因为形成了x个消费者组)。 - Madhu Bhat
显示剩余2条评论

2
根据问题,即使您有多个服务实例,也不需要担心相同消息的重新处理。因为Kafka基于消费者偏移量工作,如果您一旦读取了消息,我们就会提交该消息的偏移量,以便该消费者(组)无法再使用该消息。
让我们举个例子,订单服务在订单主题上发布消息,支付服务订阅了它。我们有10个支付服务实例。在这种情况下,假设消息1被支付服务实例1(属于默认消费者组,如果您没有明确定义)消耗。在消耗消息1后,支付服务实例1在消费者组级别上提交了该消息的偏移量,并将其视为已成功处理该消息。因此,支付服务实例2 /任何其他实例只会选择偏移量未提交的消息。
根据@Madhu的答案,这是为了更快地并行处理消息。如果您有10个支付服务实例并希望快速访问和处理消息,则可以在消费者组中添加更多消费者(但需要考虑订单主题的分区计数,因为如果订单主题有4个分区并且我们定义了5个消费者,则1个消费者始终处于空闲状态,除非任何其他消费者停止)。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接