关于 RocketMQ中 GroupID 与 Topic 订阅关系的疑问

  • Post author:
  • Post category:其他

问题

在阿里云服务提供的消息队列服务(RocketMQ)中,给出了一份关于订阅关系一致的最佳实践,在文档中指出同一个 GroupID 中的所有消费者实例最好订阅同样的 Topic+Tag。这让我有一些疑问,为什么一个 GroupID 只能产生一种订阅,这样岂不是同一个应用需要订阅不同的 Topic 那么每一次都需要去申请一个 GroupID,这使得 GroupID 和 Topic 产生了一定的耦合关系,看起来是不太合理的,那么为什么 RocketMQ 要这么做呢?

解答

经过对源码的阅读找到了一部分关于这个问题的答案。

如果同一个 GroupID 下的不同消费者实例,订阅了不同的 Topic+Tag 将导致在对Topic 的消费队列进行负载均衡的时候产生不正确的结果,最终导致消息丢失。

在消费者客户端有一个名为 Rebalance 的类,会周期性的对消费者和订阅的 Topic 的消费队列(类似于 Kafka 的 Partition)进行负载均衡。在进行负载均衡的过程中,需要通过 mqClientFactory.findConsumerIdList(topic,consumerGroup) 方法去获取在这个 GroupId下所有订阅这个 topic 的 clientId。
调用客户端获取当前 GroupID 订阅 Topic 的 ClientId

看到这个地方就有一些疑问了,命名这里有根据 GroupID 和 Topic 作为参数去获取 ClientID 怎么会产生问题呢?继续往下看。

具体获取订阅的 ClientID
我们可以看到 findConsumerIdList 方法中并没有把 Topic 继续往下传递,而仅仅是用topic 作为一个获得 Broker 地址的参数,在实际之后获取 ClientId 的方法中并没有传入 Topic。这样就会导致这个调用会返回当前 GroupID 下所有的消费者实例,无论这个消费者是否订阅了当前这个 Topic。返回的 ClientID 会参与当前 Topic 的消费对类的负载均衡,如果没有订阅这个 Topic 的消费者实例被分配到了消息队列,就会导致消费队列中的消息消费失败。


版权声明:本文为A__loser原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。