史上最全MQ高级(加更中)

54 阅读3分钟

MQ高级

生产者重连

有的时候由于网络波动 可能导致客户端连接MQ失败的情况 这个时候可以进行重连设置 就是连接失败之后的重连机制

image.png

生产者确认

更侧重的是发送消息的时候 拥有publisher confirms 以及 publisher returns 两种确认机制 用于向生产者返回确认信息

  • 消息投递到了MQ但是路由失败 比如没有找到对应的key 或者交换机根本没有绑定任何队列 这时会通过publisher returns 返回路由异常原因 也会返回ACK
  • 临时消息投递到了mq 比如投递到了一个没有做 持久化的队列里面 会返回ACK
  • 对于持久消息而言 投递到了一个做了持久化的队列里面 并且持久化成功了的话就会返回ACK
  • 其他情况会但会NACK

spring AMQP 实现生产者确认

image.png return机制一般是路由未匹配到 一般无需开启的

  • 每一个rabbitTemplate 只能配置一个returncallback 可以通过aware接口对Template对象来setReturnCallBack 方法
@Configuration
public class RabbitConfig implements ApplicationContextAware {

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        RabbitTemplate rabbitTemplate = applicationContext.getBean(RabbitTemplate.class);
        rabbitTemplate.setReturnCallback((message, replaycode, replayText, exchange, routintKey) -> {
            System.out.println(message+";;;"+replaycode+";;;"+replayText+";;;;"+exchange+";;;"+routintKey);
        });
    }
}
  • confirmcallback 只能在每一个消息发送的时候单独指定
@GetMapping("/send/{message}")
@ResponseBody
public String sendMessage(@PathVariable String message) {
    CorrelationData cd = new CorrelationData(UUID.randomUUID().toString());
    cd.getFuture().addCallback(new ListenableFutureCallback<CorrelationData.Confirm>() {
        @Override
        public void onFailure(Throwable ex) {
            log.error("消息投递错了");
            System.out.println("你好 消息失败了");
        }

        @Override
        public void onSuccess(CorrelationData.Confirm result) {
            log.error("消息投递成功");
            System.out.println("消息发送成功");
            if(result.isAck()){
                System.out.println("消息收到ACK");
            }else{


                System.out.println("你好 收到NACK"+result.getReason());}
        }
    });
    rabbitTemplate.convertAndSend("directExchange","L3OL",message+UUID.randomUUID().toString(),cd);
    //rabbitTemplate.convertAndSend("object.queue", (Object) (message + UUID.randomUUID().toString()),cd);
    return "hello,MQ!"+message;
}

就是在发送消息的时候绑定一个回调如果消息返回NACK的话就 做一个重新发送的处理以保证一个消息投递的可靠性

MQ的可靠性

image.png image.png

消费者的可靠性

消费者确认机制

image.png

  • spring amqp 实现的消费者确认机制

image.png

image.png

  • 失败自动重试 可以在listener侧做一个失败重试 防止消息一异常就返回到MQ

image.png

  • 失败消息策略处理

image.png 重试耗尽后,将失败消息投递到指定的交换机步骤 image.png

消费者如何保证消息一定被消费?

image.png

业务幂等性

image.png

唯一消息ID

image.png

image.png 幂等这个概念 可以从消息重复消费来处理 也可以从业务来判断 就是允许消息的重复消费 但是业务方法 比如减库存 支付 等做幂等处理

面试题 -- 如何保证支付服务和交易服务之间订单状态的一致性?

image.png

终极拷打 -- 如果交易服务消息处理失败 有没有什么兜底方案?

image.png

延迟消息

延迟消息概念:生产者发送一个消息指定一个时间,消费者不会立即收到消息,而是在指定时间之后再收到消息

死信交换机

image.png

  • 死信交换机工作方式 以及实现延迟消息

image.png

延迟消息插件

image.png

image.png

取消超时订单

大部分订单 都会尽快支付 如果每个订单的延迟消息一直在MQ中 会耗费CPU资源 因此可以优化

image.png

image.png 注意支付服务可能已经支付 但是业务订单仍然显示未支付 还有就是回复库存可能是跨库操作 注意分布式事务的问题