分散トランザクションの最終的な一貫性のロック解除ロジック

ここに画像の説明を挿入
ここに画像の説明を挿入
ここに画像の説明を挿入
ここに画像の説明を挿入
実装1はバッチ操作に似ており、実装2はバッチ操作ではないため、お勧めしません。

ここに画像の説明を挿入
最後に、これに最適化することができます。1つのスイッチ、2つの異なるルートが2つの異なるキューにバインドされ、そのうちの1つはデッドレターキューです。
ここに画像の説明を挿入
この図、2つのキューに基づいてスイッチを作成し、
依存関係導入します

<!--  引入RabbitMQ消息队列-->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-amqp</artifactId>
</dependency>

構成情報を追加します。

#配置rabbitmq
spring:
  rabbitmq:
    host: 81.68.112.20
    port: 5672
    #虚拟主机
    virtual-host: /
    #开启发送端确认 发送的过程中
    publisher-confirms: true
    #开启发送端确认 抵达队列
    publisher-returns: true
    template:
      #抵达队列,以异步模式优先回调组合ReturnCallback
      mandatory: true
    listener:
      simple:
        #手动ack消息 手动确认收货 手动确认模式 防止消息丢失
        acknowledge-mode: manual
//开启RabbitMQ消息队列
@EnableRabbit
@Configuration
public class MyRabbitMQConfig {
    
    

    @Autowired
    RabbitTemplate rabbitTemplate;

    //监听正常的那个队列
    @RabbitListener(queues = "order.release.order.queue")
    public void listening(OrderEntity entity, Channel channel, Message message) throws IOException {
    
    
        System.out.println("收到过期的订单,准备关闭订单。order:"+entity.getOrderSn());
        channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);
    }

    //容器中的组建Queue Exchange Binding 都会自动创建(前提是RabbitMQ没有)
    //创建一个死信队列
    @Bean
    public Queue orderDelayQueue() {
    
    

        // String name, boolean durable, boolean exclusive, boolean autoDelete,
        //			@Nullable Map<String, Object> arguments
        Map<String, Object> arguments = new HashMap<>();
        arguments.put("x-dead-letter-exchange", "order-event-exchange");//死信交换机
        arguments.put("x-dead-letter-routing-key", "order.release.order");//死信路由键
        arguments.put("x-message-ttl", 60000);//消息过期时间 ms 1分钟
        return new Queue("order.delay.queue", true, false, false, arguments);
    }

    //创建一个普通的队列
    @Bean
    public Queue orderReleaseOrderQueue() {
    
    

        //普通队列
        return new Queue("order.release.order.queue", true, false, false);
    }

    @Bean
    public Exchange orderEventExchange() {
    
    

        // String name, boolean durable, boolean autoDelete, Map<String, Object> arguments
        //普通交换机
        return new TopicExchange("order-event-exchange", true, false);
    }

    @Bean
    public Binding orderCreateOrderBinding() {
    
    

        //和延时队列绑定
        return new Binding("order.delay.queue",
                Binding.DestinationType.QUEUE,
                "order-event-exchange",
                "order.create.order",
                null);
    }

    @Bean
    public Binding orderReleaseOrderBinding() {
    
    

        //和普通队列绑定
        return new Binding("order.release.order.queue",
                Binding.DestinationType.QUEUE,
                "order-event-exchange",
                "order.release.order",
                null);
    }

    @Bean
    public Binding orderReleaseOtherBinding() {
    
    

        //订单释放直接和库存释放进行绑定
        return new Binding("stock.release.stock.queue",
                Binding.DestinationType.QUEUE,
                "order-event-exchange",
                "order.release.other.#",
                null);
    }

    @Bean
    public MessageConverter messageConverter() {
    
    

        return new Jackson2JsonMessageConverter();
    }
//
//    /**
//     * 定制rabbitTemplate
//     * 1.publisher-confirms: true
//     * 3.消费端确认 (保证每个消息被正确消费 此时才可以braker删除这个消息)
//     * 1.默认是自动确认的 只要消息接收到  客户端自动确认服务端就要移除这个消息
//     * 问题 :
//     * 收到很多消息 自动回复给服务器ack 只有一个消息处理成功 宕机了 发现消息丢失
//     * 手动确认模式: 只要我们没有确认高随MQ 货物被签收 没有ack
//     * 消息就一直是unacked状态 即使Consumer宕机 消息不会丢失 会重新变成ready
//     * 2.如果签收
//     */
    @PostConstruct  //MyRabbitConfig对象创建完成以后执行这个方法
    public void initRabbitTemplate() {
    
    

        //设置确认回调 消息到了队列
        rabbitTemplate.setConfirmCallback(new RabbitTemplate.ConfirmCallback() {
    
    

            /**
             * 1、消息抵达服务器 ack=true
             * @param correlationData 当前消息唯一关联的数据 这个是消息唯一id
             * @param ack 消息是否成功收到
             * @param cause 失败的原因
             */
            @Override
            public void confirm(CorrelationData correlationData, boolean ack, String cause) {
    
    
                //服务器收到了
                System.out.println("消息抵达服务器confirm....correlationData[" + correlationData + "]==>ack[" + ack + "]cause>>>" + cause);
            }
        });

        //设置消息队列的确认回调 发送了,但是队列没有收到
        rabbitTemplate.setReturnCallback(new RabbitTemplate.ReturnCallback() {
    
    

            /**
             * 只要消息没有投递给指定的队列 就触发这个失败回调
             * @param message  投递失败的消息详细信息
             * @param replyCode 回复的状态码
             * @param replyText 回复的文本内容
             * @param exchange 当时这个消息发给那个交换机
             * @param routingKey 当时这个消息用那个路由键
             */
            @Override
            public void returnedMessage(Message message, int replyCode, String replyText, String exchange, String routingKey) {
    
    
                //报错误 未收到消息
                System.out.println("Fail!! Message[" + message + "]==>[" + exchange + "]==>routingKey[" + routingKey + "]");
            }
        });
    }
}

テスト用のインターフェースを追加します。

 @ResponseBody
 @GetMapping("/test/creatPOrder")
 public String creatPOrderTest() {
    
    
     OrderEntity entity = new OrderEntity();
     entity.setOrderSn("10010");
     entity.setModifyTime(new Date());
     //给MQ发消息
     rabbitTemplate.convertAndSend("order-event-exchange", "order.create.order", entity);
     return "ok";
 }

あなたは1分でコンソールにメッセージを見ることができます
ここに画像の説明を挿入

おすすめ

転載: blog.csdn.net/u014496893/article/details/114239880