Halo

A magic place for coding

0%

RocketMQ消费模式详解

RocketMQ消费模式详解

Background

  在使用消息队列进行解耦的微服务架构中,如何让mq不成为流量的瓶颈呢?关于mq的并发消费,真的只是增加机器就能达到水平扩容的效果吗?在这篇博客我将介绍RocketMQ的消费机制,以及如何去提高消费能力。


Problem

  先来看看面对的是什么问题。假设以下两种场景:

  1. 在抢红包场景下,服务端收到来自客户端的请求,需要写入数据库的,在高峰时期客户端的请求量很大,需要用到MQ来削峰填谷。这个时候如果消费能力比较弱的话,可能客户端查询余额的时候就会不准确,因为数据还没有写入,都在MQ中积压
  2. 在日志分析场景下,各个服务的日志信息都写入到MQ中,然后有固定的数据分析服务去汇总信息。各个服务产生的日志信息是非常巨量的,如果消费能力不高的话,就会导致分析结果比较滞后。

  以上两个问题都是消息在队列中积压导致的,所以我们需要尽可能地提高消费能力,不让消息在队列中积压。


Solution

  提升消费能力一般有两种:垂直扩展水平扩展垂直扩展指的是使用性能更高的机器,这个提升是有限的,而且价格也是更加昂贵的,所以一般我们不会选择这种方法。水平扩展指的是使用更多的同类型机器,通过分布式、并发等操作,提升系统的整体性能。提升MQ的消费能力,我们考虑的时候水平方向上的扩展。这里我讨论两种方式,一个是增加机器(实例),另一个是增加worker(线程)。我们关注的重点是怎么样增加才是最有效的?

  首先我们要理解RocketMQ是怎么样消费消息的。RocketMQ实际上有很多个queue,这些queue是对应着broker。比如说一个broker对应5个queue,那么如果有3个broker,那么这个topic就一共有15个queue。RocketMQ的消费是以Consumer Group的形式消费的,所以在最后的消费阶段,实际上就是Consumer Group去消费所有的queue。这其中就有负载均衡的问题了。

  这里的负载均衡说的是每一个机器(实例)均分所有的queue。假设有5个queue,两个机器(实例),那么A机器(实例)消费3个queue,B机器消费2个queue。这个时候如果新增了一个C机器,那么原来A机器消费的1一个queue将会由C机器来负责。这也就解释了为什么增加机器能够提升消费能力。从上面这个例子还能看出一个问题,就是机器的数量是不能超过queue的数量的,因为queue会分配到机器上,如果有8台机器,那么6台机器各自负责1个queue,多余的2台机器将浪费掉,所以这是消费扩容的第一个要点:机器(实例)数量不得多余queue的数量

  然后我们进入到单个机器(实例)中,去看是具体怎么消费的。很明显,消费一个队列最简单的方式就是一个一个消息拿出来,处理完一个再进行下一个。但是我们仍然有可能把这个速度提升上去。在乱序消费模式下,RocketMQ允许采用多线程(多个worker)的模式去消费,也就是说对于同一个queue,可以用多个worker同时去消费,这样消费的性能就大大提升了,而且这个提升比起提升机器要方便得多,也灵活得多。这是消费扩容的第二个要点:乱序消费模式下可以通过增加worker数量来提升消费能力

  通过上面两个方法,RocketMQ的消费能力 = worker数量 * 机器(实例)数量。所以大家以后在遇到类似的情况下,就不要盲目增加机器数量了。


Reference

  1. RocketMQ负载均衡特性
  2. RocketMQ Operations_Consumer

Welcome to my other publishing channels