rabbitMQ的消息可靠性

何为可靠性

当mq异步发送一条信息,但是mq处理消息时发生错误,无法达到预期处理结果。

比如当我们购买一件商品时,完成了支付动作,这个时候将修改订单状态交给mq处理,但是mq发生了错误,导致支付状态与订单状态不一致。

解决办法

1.生产者可靠性

1.1 retry重试机制

在yml文件中添加如下信息

    connection-timeout: 1s          #连接超时时间
    publisher-returns: true         #开启publish-return功能
    # 这里支持两种类型:simple:同步等待confirm结果,直到超时;
    # correlated:异步回调,定义ConfirmCallback,MQ返回结果时会回调这个ConfirmCallback
    publisher-confirm-type: correlated
    template:
      retry:
        enabled: true               #开启重试机制
        initial-interval: 1000ms    #初始失败等待时长
        multiplier: 1               #失败时长等待时长倍数 下次等待时长 = multiplier * initial-interval
        max-attempts: 3             #最大重试次数

1.2 生产者确认机制.

Publisher Confirm

编写配置类

public class MqConfirmConfig implements ApplicationContextAware {
    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        RabbitTemplate rabbitTemplate = applicationContext.getBean(RabbitTemplate.class);
        rabbitTemplate.setReturnsCallback(new RabbitTemplate.ReturnsCallback() {
            @Override
            public void returnedMessage(ReturnedMessage returnedMessage) {
                log.debug("收到消息的return callback,exchange:{},key:{},text:{},code:{},msg:{}",
                        returnedMessage.getExchange(),returnedMessage.getRoutingKey(),
                        returnedMessage.getReplyText(),returnedMessage.getReplyCode(),
                        returnedMessage.getMessage());
            }
        });
    }
}

Publisher Return

在发送消息时编写代码,在失败结果中处理

 void testRerun() throws InterruptedException {
        CorrelationData cd = new CorrelationData(UUID.randomUUID().toString());
        cd.getFuture().addCallback(new ListenableFutureCallback<CorrelationData.Confirm>() {
            @Override
            public void onFailure(Throwable ex) {
                log.error("消息回调失败:",ex);
            }

            @Override
            public void onSuccess(CorrelationData.Confirm result) {
                log.debug("收到confirm callback回调");
                if(result.isAck()){
                    log.debug("消息发送成功,收到ack");
                }else{
                    log.debug("消息发送失败,收到nack,原因:{}",result.getReason());
                }
            }
        });
        rabbitTemplate.convertAndSend("hmall.direct","red","hellp",cd);
        Thread.sleep(2000);
    }

2.MQ的可靠性

在默认情况下,RabbitMQ会将接收到的信息保存在内存中以降低消息收发的延迟。这样会导致两个问题:

  • 一旦MQ宕机,内存中的消息会丢失
  • 内存空间有限,当消费者故障或处理过慢时,会导致消息积压,引发MQ阻塞

2.1交换机可靠性

消费者确认机制

为了确认消费者是否成功处理消息,RabbitMQ提供了消费者确认机制,(Consumer Acknowledgement)。当消费者处理消息结束后,应该向RabbitMQ发送一个回执,告知RabbitMQ自己消息处理状。回执有三种可选值:

  • ack:成功处理消息,RabbitMQ从队列中删除该消息。
  • nack:消息处理失败,RabbitMQ需要再次投递消息。
  • reject:消息处理失败并拒绝该消息,RabbitMQ从队列中删除该消息。
spring:
  rabbitmq:
    listener:
      simple:
        acknowledge-mode: auto

在acknowledge-mode中配置,有三种方式:

  • none:不处理。即消息投递给消费者后立刻ack,消息会立即从MQ删除,非常不安全,不建议使用。
  • manual:手动模式。需要自己在业务代码中调用api,发送ack或reject,存在业务入侵,但更灵活。
  • auto:自动模式。SpringAMQP利用AOP对我们的消息处理逻辑做了环绕增强,当业务正常执行时则自动返回ack
    1. 如果是业务异常,会自动返回nack
    2. 如果是消息处理或校验异常,自动返回reject

消费者重试机制,设置MessageRecoverer

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值