精品 RabbitMQ常见问题

1.消息堆积

当消息生产的速度,远远大于消费的速度,就会造成消息堆积
图片.png

1.1 消息堆积的影响

(1) 可能导致新消息无法进入队列
(2) 可能导致旧消息无法丢失
(3) 消息等待消费的时间过长,超出了业务容忍范围

1.2 产生堆积的原因

(1)生产者突然大量发布消息
(2) 消费者消费失败
(3) 消费者出现性能瓶颈。
(4) 消费者宕机

1.3 解决办法

(1) 排查消费者的消费性能瓶颈
(2) 增加消费者的多线程处理
(3) 部署增加多个消费者
(4) 场景介绍

2.消息丢失

在实际的生产环境中有可能出现一条消息因为一些原因丢失,导致消息没有消费成功,从而造成数据不一致等问题,造成严重的影响。

比如:在常见的电商业务中需要生成订单信息和扣减库存两个动作,如果使用RabbitMQ来实现该业务,那么在订单服务下单成功后需要发送一条消息到库存服务进行扣减库存,如果在此过程中,一条消息因为某些原因丢失,那么就会出现下单成功但是库存没有扣减,从而导致超卖的情况。

消息丢失的场景主要分为:消息在生产者丢失,消息在RabbitMQ丢失,消息在消费者丢失。

(1) 在生产者丢失

采用RabbitMQ 发送方消息确认机制,当消息成功被MQ接收到时,会给生产者发送一个确认消息,表示接收成功。springBoot整合RabbitMQ后只使用了异步监听确认模式。

异步监听模式,可以实现边发送消息边进行确认,不影响主线程任务执行.

图片.png

@Component
public class ConfirmCallbackService implements RabbitTemplate.ConfirmCallback {
    @Override
    public void confirm(CorrelationData correlationData, boolean ack, String cause) {
 
        if (!ack) {
            log.error("消息发送异常!");
        } else {
            log.info("已经收到确认,correlationData={} ,ack={}, cause={}", correlationData.getId(), ack, cause);
        }
    }
}

(2) 消息在RabbitMQ丢失

消息成功发送到MQ,消息还没被消费却在MQ中丢失,比如MQ服务器宕机或者重启会出现这种情况

解决方案

持久化交换机,队列,消息,确保MQ服务器重启时依然能从磁盘恢复对应的交换机,队列和消息。

spring整合后默认开启了交换机,队列,消息的持久化,所以不修改任何设置就可以保证消息不在RabbitMQ丢失。但是为了以防万一,还是可以申明下。

(3)消息在消费者丢失

设置为手动回复MQ服务器,当消费者出现异常或者服务宕机时,MQ服务器不会删除该消息,而是会把消息重发给绑定该队列的消费者,如果该队列只绑定了一个消费者,那么该消息会一直保存在MQ服务器,

直到消息者能正常消费为止。

3. 重复消费

为了防止消息在消费者端丢失,会采用手动回复MQ的方式来解决,同时也引出了一个问题,消费者处理消息成功,手动回复MQ时由于网络不稳定,连接断开,导致MQ没有收到消费者回复的消息,

会重新把该条消息发给和该队列绑定的消息者处理,这样就会导致消息重复消费。

解决方案

如果消费消息的业务是幂等性操作(同一个操作执行多次,结果不变)就算重复消费也没问题,可以不做处理,如果不支持幂等性操作,

如:下单,减库存,扣款等,那么可以在消费者端每次消费成功后将该条消息id保存到数据库,每次消费前查询该消息id,如果该条消息id已经存在那么表示已经消费过就不再消费否则就消费。

本方案采用redis存储消息id,因为redis是单线程的,并且性能也非常好,提供了很多原子性的命令,本方案使用setnx命令存储消息id。

4. 顺序消费

①一个queue,有多个consumer去消费,这样就会造成顺序的错误,consumer从MQ里面读取数据是有序的,但是每个consumer的执行时间是不固定的,无法保证先读到消息的consumer一定先完成操作,这样就会出现消息并没有按照顺序执行,造成数据顺序错误。

图片.png

1)解决方案 比如 消息1 消息2 消息3 有依赖性 消息4 消息5 消息6有依赖性

①拆分多个queue,每个queue一个consumer,就是多一些queue而已,将有顺序的消息分组,比如 A 组 消息1

消息2 消息3 B组 消息4 消息5 消息6 这种方式处理。

图片.png

2)加入因为消息者内部因为多线程执行导致的顺序错乱问题

将消息分组封装好,发给不同的线程执行即可。

图片.png

暂无数据
关注 私信
文章 专栏 文档 话题

相关推荐

  • SpringBoot整合RabbitMQ
  • RabbitMQ持久化和ACK应答
  • RabbitMQ的消息模型
  • RabbitMQ的应用场景
  • RabbitMQ介绍及安装
联系客服