<dependency>
<groupId>org.apache.rocketmqgroupId>
<artifactId>rocketmq-spring-boot-starterartifactId>
<version>2.2.1version>
dependency>
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
发送事务消息
@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";
}
}
真正事务
@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