boot - rocketmq 事务消息

boot - rocketmq 事务消息

依赖

<dependency>
    <groupId>org.apache.rocketmqgroupId>
    <artifactId>rocketmq-spring-boot-starterartifactId>
    <version>2.2.1version>
dependency>

properties配置文件

rocketmq.name-server=192.168.xxx.10:9876
rocketmq.producer.group=group1
rocketmq.producer.send-message-timeout=3000
rocketmq.producer.compress-message-body-threshold=4096
rocketmq.producer.max-message-size=4194304
rocketmq.producer.retry-times-when-send-async-failed=3
#异步消息发送失败重试的次数
rocketmq.producer.retry-times-when-send-failed=3

RcController

发送事务消息

@RestController
public class RcController {

    @Autowired
    private RocketMQTemplate rocketMQTemplate;

    @Autowired
    private ObjectMapper objectMapper;


    @GetMapping("/send")
    public String send() {
        String orderId = UUID.randomUUID().toString().replace("-", "");
        RcOrder rcOrder = new RcOrder();
        rcOrder.setOrderNo(orderId);
        rcOrder.setUserId("2");
        rcOrder.setUserName("tom");
        rcOrder.setUserNickName("jack");
        rcOrder.setCreateTime(LocalDateTime.now());
        rcOrder.setCreateUser("tom");
        rcOrder.setUpdateTime(LocalDateTime.now());
        rcOrder.setUpdateUser("jack");
        TransactionSendResult result = rocketMQTemplate.sendMessageInTransaction("trx-topic",
                MessageBuilder.withPayload(rcOrder).setHeader(RocketMQHeaders.TRANSACTION_ID, orderId).build(), null);
        try {
            System.out.println(objectMapper.writeValueAsString(result));
        } catch (JsonProcessingException e) {
            e.printStackTrace();
        }
        return "ok";
    }

}

RcOrderServiceImpl

真正事务

@Slf4j
@Service
public class RcOrderServiceImpl extends ServiceImpl<RcOrderMapper, RcOrder>
        implements RcOrderService {

    @Autowired
    private RocketMQTemplate rocketMQTemplate;
    @Autowired
    private ObjectMapper objectMapper;
    private AtomicInteger c = new AtomicInteger(0);

    @Override
    @Transactional
    public boolean saveOrder(RcOrder order) {
        log.info("start insert: " + order.getOrderNo());
        int a = baseMapper.insert(order);
        if (c.incrementAndGet() % 3 == 0) {
            throw new RuntimeException("异常");
        }
        return a > 0;
    }
}


消费者

@Service
@RocketMQMessageListener(consumerGroup = "group1", topic = "trx-topic", messageModel = MessageModel.CLUSTERING)
public class RcConsumerListener implements RocketMQListener<RcOrder> {

    @Autowired
    private ObjectMapper objectMapper;

    @Override
    public void onMessage(RcOrder s) {
        try {
            System.out.println("consumer msg: " + objectMapper.writeValueAsString(s));
        } catch (JsonProcessingException e) {
            e.printStackTrace();
        }
    }
}

事务消息执行本地事务监听

@Slf4j
@Service
@RocketMQTransactionListener
public class OrderTransListener implements RocketMQLocalTransactionListener {

    @Autowired
    private RcOrderService rcOrderService;
    @Autowired
    private ObjectMapper objectMapper;

    @Override
    public RocketMQLocalTransactionState executeLocalTransaction(Message message, Object o) {

        log.info("执行本地事务....");
        try {
            String str = new String((byte[]) message.getPayload(), StandardCharsets.UTF_8);
            RcOrder order = objectMapper.readValue(str, RcOrder.class);
            boolean b = rcOrderService.saveOrder(order);
            return b ? RocketMQLocalTransactionState.COMMIT : RocketMQLocalTransactionState.ROLLBACK;
        } catch (Exception e) {
            log.error("executeLocalTransaction error: ", e);
            return RocketMQLocalTransactionState.ROLLBACK;
        }
    }

    @Override
    public RocketMQLocalTransactionState checkLocalTransaction(Message message) {
        log.info("回查本地事务....");

        try {
            String str = new String((byte[]) message.getPayload(), StandardCharsets.UTF_8);
            RcOrder order = objectMapper.readValue(str, RcOrder.class);
            if (isSuccess(order.getOrderNo())) {
                return RocketMQLocalTransactionState.COMMIT;
            }
        } catch (JsonProcessingException e) {
            log.error("checkLocalTransaction error: ", e);
        }
        return RocketMQLocalTransactionState.ROLLBACK;
    }

    private boolean isSuccess(String orderNo) {
        LambdaQueryWrapper<RcOrder> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(RcOrder::getOrderNo, orderNo);
        RcOrder rcOrder = rcOrderService.getOne(queryWrapper);
        return rcOrder != null;
    }
}

结果:

c.example.r.order.mq.OrderTransListener  : 执行本地事务....
c.e.r.o.service.impl.RcOrderServiceImpl  : start insert: 41e9af01e64841c69c07f7db4fca4949
{"sendStatus":"SEND_OK","msgId":"7F000001FBDC18B4AAC23047FF250000","messageQueue":{"topic":"trx-topic","brokerName":"broker-a  ","queueId":2},"queueOffset":32,"transactionId":null,"offsetMsgId":null,"regionId":null,"traceOn":true,"localTransactionState":"COMMIT_MESSAGE"}
consumer msg: {"id":null,"orderNo":"41e9af01e64841c69c07f7db4fca4949","userId":"2","userName":"tom","userNickName":"jack","createTime":"2022-11-10T09:00:24.646","createUser":"tom","updateTime":"2022-11-10T09:00:24.647","updateUser":"jack"}
c.example.r.order.mq.OrderTransListener  : 执行本地事务....
c.e.r.o.service.impl.RcOrderServiceImpl  : start insert: b4fb584111f5497fb3e8727796e14ab0
{"sendStatus":"SEND_OK","msgId":"7F000001FBDC18B4AAC2304801370001","messageQueue":{"topic":"trx-topic","brokerName":"broker-a  ","queueId":3},"queueOffset":33,"transactionId":null,"offsetMsgId":null,"regionId":null,"traceOn":true,"localTransactionState":"COMMIT_MESSAGE"}
consumer msg: {"id":null,"orderNo":"b4fb584111f5497fb3e8727796e14ab0","userId":"2","userName":"tom","userNickName":"jack","createTime":"2022-11-10T09:00:25.271","createUser":"tom","updateTime":"2022-11-10T09:00:25.271","updateUser":"jack"}
c.example.r.order.mq.OrderTransListener  : 执行本地事务....
c.e.r.o.service.impl.RcOrderServiceImpl  : start insert: 93956b2e308f4c14b6152d649cd90c50
{"sendStatus":"SEND_OK","msgId":"7F000001FBDC18B4AAC2304803990002","messageQueue":{"topic":"trx-topic","brokerName":"broker-a  ","queueId":0},"queueOffset":34,"transactionId":null,"offsetMsgId":null,"regionId":null,"traceOn":true,"localTransactionState":"ROLLBACK_MESSAGE"}

可以发现 发送事务消息时,先执行本地事务,后拿到事务本地事务的提交的结果,一次是 COMMIT_MESSAGE, 一次是 ROLLBACK_MESSAGE

你可能感兴趣的:(每日一问,rocketmq)