• RocektMQ事务


    一、简介

    RocketMQ是一种最终一致性的分布式事务,就是说它保证的是消息最终一致性

     

    A、MQ发送方先发送个Half MessageBroker端,消息中携带MQ订阅方需要的消息。

    B、当MQ发送方知道Half Message发送成功后,那么开始第C步执行本地事务。

    C、执行本地事务(会有三种情况1、执行成功。2、执行失败。3、网络等原因导致没有响应)

    D、如果本地事务成功,那么ProductBroker服务器发送Commit,这样MQ订阅方就可以消费该message;如果本地事务失败,那么ProductBroker服务器发送Rollback,那么就会直接删除上面这条半消息。

    E、如果因为网络等原因迟迟没有返回失败还是成功,那么会执行RocketMQ的回调接口,来进行事务的回查。

    F、检查本地事务状态。

    G、根据第F步检查的状态反馈给BrokerCommit即投递消息到MQ订阅方,Rollback即删除消息。

    二、代码

    public class OrderService {
      public static void main(String[] args) throws Exception {
        TransactionMQProducer producer = new TransactionMQProducer();
        producer.setNamesrvAddr(RocketMQConstants.NAMESRV_ADDR);
        producer.setProducerGroup(RocketMQConstants.TRANSACTION_PRODUCER_GROUP);
    
        //自定义线程池,执行事务操作
        ThreadPoolExecutor executor = new ThreadPoolExecutor(10, 50, 10L, TimeUnit.SECONDS, new ArrayBlockingQueue<>(20), (Runnable r) -> new Thread("Order Transaction Massage Thread"));
        producer.setExecutorService(executor);
    
        //设置事务消息监听器
        producer.setTransactionListener(new OrderTransactionListener());
    
        producer.start();
    
        System.err.println("OrderService Start");
    
        for (int i = 0;i < 10;i++){
          String orderId = UUID.randomUUID().toString();
          String payload = "下单,orderId: " + orderId;
          String tags = "Tag";
          Message message = new Message(RocketMQConstants.TRANSACTION_TOPIC_NAME, tags, orderId, payload.getBytes(RemotingHelper.DEFAULT_CHARSET));
    
          //发送事务消息
          TransactionSendResult result = producer.sendMessageInTransaction(message, orderId);
          System.err.println("发送事务消息,发送结果: " + result);
        }
      }
    }
    View Code
    public class OrderTransactionListener implements TransactionListener {
      private static final Map<String, Boolean> results = new ConcurrentHashMap<>();
    
      @Override
      public LocalTransactionState executeLocalTransaction(Message msg, Object arg) {
        String orderId = (String) arg;
    
        //记录本地事务执行结果
        boolean success = persistTransactionResult(orderId);
        System.err.println("订单服务执行本地事务下单,orderId: " + orderId + ", result: " + success);
        return success ? LocalTransactionState.COMMIT_MESSAGE : LocalTransactionState.ROLLBACK_MESSAGE;
      }
    
      @Override
      public LocalTransactionState checkLocalTransaction(MessageExt msg) {
        String orderId = msg.getKeys();
        System.err.println("执行事务消息回查,orderId: " + orderId);
        return Boolean.TRUE.equals(results.get(orderId)) ? LocalTransactionState.COMMIT_MESSAGE : LocalTransactionState.ROLLBACK_MESSAGE;
      }
    
      private boolean persistTransactionResult(String orderId) {
        boolean success = Math.abs(Objects.hash(orderId)) % 2 == 0;
        results.put(orderId, success);
        return success;
      }
    }
    View Code

    说明:

    A、executeLocalTransaction方法中可执行本地事务,其返回状态可为COMMIT(事务提交)、ROLLBACK(事务回滚)、UNKNOWN(未知),如果为UNKNOWN状态或者没有返回状态会进入checkLocalTransaction方法,即检查本地事务的执行状态方法。

    B、checkLocalTransaction方法为检查本地事务方法其返回值为COMMIT(事务提交)、ROLLBACK(事务回滚)、UNKNOWN(未知),如果为UNKNOWN状态则下一次检查时还会进入此方法检测本地事务,默认检查间隔为6000ms,检查次数为15次。

    C、checkLocalTransaction方法中也可以定义检测次数,如三次,可存为Redis中,key为事务idvalue为次数,如果到达三次那么直接返回ROLLBACK.

  • 相关阅读:
    使用Git进行代码管理的心得
    软件工程的实践项目的自我目标
    第五次作业——团队项目——需求规格说明书
    第三次作业——结对编程
    第六次作业——团队作业
    调研Android平台的开发环境的发展演变
    第四次作业——个人作业——软件案例分析
    IT人士 不能一辈子靠技术生存
    Launchy、FARR、AutoHotKey哪个快速启动软件好?
    申请了好几次,终于通过了!庆祝一下!
  • 原文地址:https://www.cnblogs.com/TimeSay/p/14803822.html
Copyright © 2020-2023  润新知