问题复现:
服务A 保存mysql多个表,多个表要在一个事务内操作,同时还要调用服务B的MQ数据处理,要求服务A的mysql操作和服务B的MQ数据操作要在一个事务内进行,要么同时成功,要么同时失败
解决方案1:
将服务B的MQ发送放在服务A的mysql事务内,问题:如果服务A的mysql失败可以回滚,服务B的MQ无法回滚,这里加个try catch 进行拟补操作也可以
解决方案2:
引入rocketMQ的事务发送消息,先对服务B的MQ发送成功状态进行尝试,如果能确定发送成功,执行服务A的mysql操作,只有服务A的mysql操作成功了,才会发送服务B的MQ发送,失败了就一起回滚。
OrderRefundApplyMessage message = refundApplyService.buildEvent(OrderRefundApplyMessage.EventType.NEW_RECEIVE_ADDRESS_CHANGE, refundApply, operateId);
ReceiveAddressChange finalChange = change;
TransactionSendResult sendResult = producer.sendMessageInTransaction(RocketMQConst.TopicChdOrder.TOPIC,
RocketMQConst.TopicChdOrder.Tag.REFUND_APPLY,
message,
() -> {
refundApplyService.save(refundApply);
addressChangeApplyService.save(addressChangeApply);
addressChangeApplyRecordService.save(addressChangeApplyRecords);
if (null != finalChange) {
addressChangeService.save(finalChange);
}
});
if (sendResult.getLocalTransactionState() != LocalTransactionState.COMMIT_MESSAGE) {
throw new ChdIgnorableException("申请失败");
}