
当生产者发送消息的速度超过了消费者处理消息的速度,就会导致队列中的消息堆积,直到队列存储消息到达上限。
解决消息堆积问题通常有这样几种方案。
一、消费者角度
①增加消费者数量,当消费者处理速度跟不上生产者发送消息的速度时,可以通过增加更多的消费者实例来并行处理消息,从而提升总体处理能力。
②优化消费者性能:提升单个消费者处理速度,分析消费者代码,提升代码效率、增加资源。
二、队列角度
①增加队列容量。
②设置消息过期时间。为消息设置有效期,过期的消息会自动从队列中清除或转发到其他队列,这样可以避免长期堆积无用消息。
③使用优先级队列,对于不同优先级的消息,可以配置优先级队列,确保高优先级的消息优先被处理,降低低优先级消息对系统造成的压力。
④使用死信交换机。对于无法立即处理或处理失败的消息,可以配置死信交换器和队列。当消息达到一定重试次数或者超过一定期限未被成功消费时,消息将被转发到死信队列中,后续可以单独处理这部分消息,避免阻塞正常的消息流。
⑤使用惰性队列。对于传统的队列来讲,如果没有开启消息持久化,所有接收到的消息都是放在内存里面的,这样性能会很好,但是也带来了一个问题,RabbitMQ 设置了一个内存预警值(内存存储的上限,默认是 40%),如果在消息堆积的情况下,很容易就到达这个预警值,此时,RabbitMQ 就会处于一个暂停状态,会阻止生产者投递消息进来,然后把内存中的一部分消息清理出来,刷出到磁盘中,这动作也叫 "page out" . 进而导致 mq 的并发能力,忽高忽低,性能不稳定(每次page out 都会比较耗时,停顿一段时间。而惰性队列,收到的消息会直接写入磁盘,而非内存,也因此很难触发 mq 的内存预警,几乎不会出现 page out 的情况。消费者消费惰性队列的消息,也需要先从磁盘中读取并加载到内存中. 实际上这也会使延迟稍微高一点,毕竟磁盘的性能和内存还是有很大差距的,但是也在可以接收到范围内。支持数百万的消息存储,这也是因为他是磁盘存储(空间非常大)