- 本地方法发送消息至borker
- borker 执行TransactionListener的方法。执行本地事务executeLocalTransaction
- 如果返回unkow状态,borker会回调checkLocalTransaction检查事务的结果,返回提交还是回滚
- borker设置消息对外可见,等待消费或主动推送
事务消息共有三种状态,提交状态、回滚状态、中间状态:
- TransactionStatus.CommitTransaction: 提交事务,它允许消费者消费此消息。
- TransactionStatus.RollbackTransaction: 回滚事务,它代表该消息将被删除,不允许被消费。
- TransactionStatus.Unknown: 中间状态,它代表需要检查消息队列来确定状态。
事务的流程如下图简述
发送事务消息
代码演示
发送一个消息(第一步)
rocketMQTemplate.sendMessageInTransaction("send_message_to_ipc",
"ipo-system-notice-topic",
MessageBuilder.withPayload(JSONUtil.toJsonStr(entity)).build(),
null);
Borker回查本地事务并执行本地事务,根据本地事务返回commit还是rollback(第二三四步)
@Component
@RocketMQTransactionListener(txProducerGroup = "send_message_to_ipc")
public static class SendMessageToIpcExecuteLocal implements RocketMQLocalTransactionListener {
@Autowired
TNoticeMapper tNoticeMapper;
@Override
public RocketMQLocalTransactionState executeLocalTransaction(Message msg, Object arg) {
String body = new String((byte[]) msg.getPayload(), StandardCharsets.UTF_8);
TNotice bean = JSONUtil.toBean(body, TNotice.class);
bean.setType("1");
// 本地事务
return tNoticeMapper.insert(bean) != 0 ?
RocketMQLocalTransactionState.COMMIT
: RocketMQLocalTransactionState.ROLLBACK;
}
@Override
public RocketMQLocalTransactionState checkLocalTransaction(Message msg) {
return null;
}
}
等待消费者消费(第六步)。。
@Slf4j
@Component
@RocketMQMessageListener(topic = "ipo-system-notice-topic", consumerGroup = "ipc-system-notice-group")
public class MQSystemNoticeListener implements RocketMQListener<String>, RocketMQPushConsumerLifecycleListener {
@Autowired
IdUtils idUtils;
@Autowired
TCmNoticeMapper cmNoticeMapper;
@Autowired
TCmUserOrganMapper cmUserOrganMapper;
@Override
public void onMessage(String message) {
List<TCmUserOrgan> organs = cmUserOrganMapper.selectList(null);
TCmNotice notice = JSONUtil.toBean(message, TCmNotice.class);
ArrayList<TCmNotice> list = new ArrayList<>();
for (TCmUserOrgan organ : organs) {
TCmNotice dto = new TCmNotice();
dto.setId(idUtils.nextIdStr());
dto.setTopic(notice.getTopic());
dto.setContent(notice.getContent());
dto.setType("1");
dto.setStatus("1");
dto.setOrganId(organ.getOrganId());
dto.setUserId(organ.getUserId());
list.add(dto);
}
cmNoticeMapper.saveBatch(list);
log.info("保存系统消息成功:{}", message);
}
@Override
public void prepareStart(DefaultMQPushConsumer consumer) {
consumer.setMaxReconsumeTimes(5);
}
}