一、前提引入

        在微服务盛行的当下,MQ被使用的也是越来越多,一般常用来进行业务异步解耦、解耦微服务、流量削峰填谷、消息分发等等,而在公司里面,由于Kafka的消息可靠性一般,因此我们通常使用它用于一些日志的输出方面。而在我们业务方面,我们会选择RabbitMQ或者RocketMQ这些消息中间件。

        以RabbitMQ为例,如果RabbitMQ出现了消息堆积的问题,我们该怎么办呢?首先我们可以思考一下,什么时候会出现消息堆积的问题呢?

        显然,这和我们平常生活卖东西一样,当商家生产者产生的速度大于我们消费者消费的速度,商家那边的商品就会堆积。类比到我们的RabbitMQ上,当我们生产产生的消息速度大于消费者消费的速度时,就会造成消息堆积。那我们该如何解决?下面给出答案~~~

二、解决方案

        如上面将到的,消息堆积问题产生的原因往往是因为消息发送的速度超过了消费者消息处理的速度。因为对应上面的问题,我们无外乎可以给出以下几个解决方案。

(1)提高消费者处理速度

        这个其实也挺好理解的嘛,只要消费者的消费处理速度大于我们生产者产生的速度,堆积的信息会慢慢减少,这样子就可以实现不出现消息堆积的问题。对应于MQ中,消费者处理速度是由业务代码决定的,我们只要实现:1)优化我们的业务代码,提高业务性能 。2)接收到消息后,开启线程池,通过并发的方式处理多个消息。

  • 优点:成本相对较低,只需要改改代码即可。
  • 缺点:由于需要开启线程池,因此会带来额外的性能开销,对于低时延、高频的任务其实不太适用。(推荐任务周期较长的业务使用)

(2)提高更多的消费者

        这里可以举个例子:在一个商场里,出现了商品堆积的问题,这时候如果商场进行低价大甩卖啊,什么9.9秒杀之类的活动一般都会有更多的大爷大妈进来疯狂购买,这就是一种商品堆积的手段。(但是廉价销售商品,费钱且亏钱!)

        显然,对应我们的MQ,当我们消费者变多的时候,消费速度就会大大提升,堆积的消息就会被慢慢消费掉。优缺点如下:

能用钱解决的问题都算不上问题~~

成本太高,没钱

(3)增加队列消息存储上限

        增加队列消息存储的上限,也就是提高MQ的存储能力。(我一个10平的仓库你说我放满商品了是卖不出去,有其他商品进来的时候不够放,你说我滞销。那我换一个更大的100平的仓库放商品,我的商品就不算滞销了,东西放得下了,这很合理!)

Lazy Queue。使用这种队列的时候,这个队列不会将我们的消息放到内存中,而是在收到了消息直接写入磁盘当中,理论上是没有存储上限的,我们的磁盘有多大,那么我们就能存储多大的内存,这样子就可以处理消息堆积的问题了。

  • 优点:磁盘存储更为安全,并且存储无上限,避免了内存存储带来的Page Out问题,性能更为稳定。
  • 缺点:由于磁盘是存储在磁盘中,因此需要进行磁盘的IO,受到IO性能的限制。同时,消息时效性不如内存模式,不过在消息堆积的背景下,影响其实是不大的。