rocketmq事务消息

该博客介绍了RocketMQ如何使用事务消息来实现分布式事务,主要涉及两阶段提交和回调复查机制。通过示例代码展示了生产者如何发送半消息、执行本地事务并根据结果提交或回滚,以及消费者如何验证消息投递。示例中,RocketMQ1、RocketMQ4、RocketMQ7预计会成功投递。
摘要由CSDN通过智能技术生成

        rocketmq事务消息可以用来实现分布式事务,其核心思想为两阶段提交,回调复查,下面是rocketmq事务消息执行流程图。

 

        1.生产者向mq发送半消息。

        2.mq收到半消息返回半消息发送成功。

        3.执行本地事务。

        4.根据本地事务执行结果判断半消息提交或回滚。 

        5.如果没有收到第四步通知则定时回调。

        6.处理回调消息,检查本地事务执行结果。

        7.根据回调消息结果判断事务消息提交或回滚。

事务消息实现代码如下:

        创建事务监听

public class TransactionListenerImpl implements TransactionListener {
  
  private AtomicInteger transactionIndex = new AtomicInteger(0);

  private ConcurrentHashMap<String, Integer> localTrans = new ConcurrentHashMap<>();

  @Override
  public LocalTransactionState executeLocalTransaction(Message msg, Object arg) {
    // 执行本地事务,状态都返回未知,等待回查
    int value = transactionIndex.getAndIncrement();
    int status = value % 3;
    localTrans.put(msg.getTransactionId(), status);
    return LocalTransactionState.UNKNOW;
  }

  @Override
  public LocalTransactionState checkLocalTransaction(MessageExt msg) {
    Integer status = localTrans.get(msg.getTransactionId());
    if (null != status) {
      switch (status) {
        case 0:
          // 未知状态
          return LocalTransactionState.UNKNOW;
        case 1:
          // 成功
          return LocalTransactionState.COMMIT_MESSAGE;
        case 2:
          // 回滚
          return LocalTransactionState.ROLLBACK_MESSAGE;
      }
    }
    return LocalTransactionState.COMMIT_MESSAGE;
  }
}

        创建发送对象

public class TransactionProducer {
  public static void main(String[] args) throws MQClientException, InterruptedException {
    // 创建监听器
    TransactionListener transactionListener = new TransactionListenerImpl();
    // 创建mq对象
    TransactionMQProducer producer = new TransactionMQProducer("transaction_producer_test");
    producer.setNamesrvAddr("ip:9876");
    producer.setInstanceName(UUID.randomUUID().toString());
    // 创建线程池处理回调
    ExecutorService executorService = new ThreadPoolExecutor(2, 5, 100, TimeUnit.SECONDS,
        new ArrayBlockingQueue<Runnable>(2000), new ThreadFactory() {
          @Override
          public Thread newThread(Runnable r) {
            Thread thread = new Thread(r);
            thread.setName("client-transaction-msg-check-thread");
            return thread;
          }
        });

    producer.setExecutorService(executorService);
    producer.setTransactionListener(transactionListener);
    producer.start();

    String[] tags = new String[] {"TagA", "TagB", "TagC", "TagD", "TagE"};
    for (int i = 0; i < 10; i++) {
      try {
        Message msg = new Message("TopicTest", tags[i % tags.length], "KEY" + i,
            ("rocketmq" + i).getBytes(RemotingHelper.DEFAULT_CHARSET));
        SendResult sendResult = producer.sendMessageInTransaction(msg, null);
        System.out.printf("%s%n", sendResult);

        Thread.sleep(10);
      } catch (MQClientException | UnsupportedEncodingException e) {
        e.printStackTrace();
      }
    }

    for (int i = 0; i < 100000; i++) {
      Thread.sleep(1000);
    }
    producer.shutdown();
  }
}

        开启消费者验证是否发送成功,按现有逻辑rocketmq1、rocketmq4、rocketmq7会成功投递。

public class Consumer {


  public static void main(String[] args) throws InterruptedException, MQClientException {
    DefaultMQPushConsumer consumer = new DefaultMQPushConsumer("transaction_consumer_test");
    consumer.setConsumeFromWhere(ConsumeFromWhere.CONSUME_FROM_FIRST_OFFSET);
    consumer.setNamesrvAddr("ip:9876");
    consumer.setInstanceName(UUID.randomUUID().toString());
    consumer.subscribe("TopicTest", "*");
    consumer.registerMessageListener(new MessageListenerConcurrently() {
      @Override
      public ConsumeConcurrentlyStatus consumeMessage(List<MessageExt> msgs,
          ConsumeConcurrentlyContext context) {
        for (Message msg : msgs) {
          System.out.println(new String(msg.getBody()) + " === date:" + new Date());
        }
        return ConsumeConcurrentlyStatus.CONSUME_SUCCESS;
      }
    });

    consumer.start();
    System.out.println("start success");
  }

}

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值