订单服务、用户服务、商品服务
1.订单服务发送事务消息
public String create() {
//发送half事务消息
orderMessageSender.sendCreateOrderMsg(123L,SecurityUtils.getMemberId());
return null;
}
//发送事务消息
@Slf4j
@Component
public class OrderMessageSender {
/*
@Value("${rocketmq.tulingmall.scheduleTopic}")
private String scheduleTopic;
@Value("${rocketmq.tulingmall.transGroup}")
private String transGroup;
@Value("${rocketmq.tulingmall.transTopic}")
private String transTopic;*/
@Value("${rocketmq.tulingmall.asyncOrderTopic}")
private String asyncOrderTopic;
private String TAG = "cancelOrder";
private String TXTAG = "trans";
private String ORDERTAG = "create-order";
@Autowired
private RocketMQTemplate rocketMQTemplate;
/**
* 使用事务消息机制发送订单
* @return
*/
public boolean sendCreateOrderMsg(Long orderId, Long memberId){
String destination = asyncOrderTopic+":"+ORDERTAG;
Message<String> message = MessageBuilder.withPayload(orderId+":"+memberId)
.build();
TransactionSendResult sendResult = rocketMQTemplate.sendMessageInTransaction(destination,message,orderId);
return SendStatus.SEND_OK == sendResult.getSendStatus();
}
}
/**
* 订单事务消息监听器
*/
@Slf4j
@RocketMQTransactionListener()
public class TransactionListenerImpl implements RocketMQLocalTransactionListener {
@Autowired
private RedisTemplate redisTemplate;
@Autowired
TransactionLogService transactionLogService;
/**
* 回查次数可以根据订单超时事件定制,普通订单超时时间来自于oms_order_settings
* 下单事务消息的本地事务
* redis中记录回查的次数
* 返回UNKNOWN状态,等待事务回查
* 监听到发送half消息,执行本地事务
*/
@Override
public RocketMQLocalTransactionState executeLocalTransaction(Message msg, Object arg) {
log.info("order开始执行本地事务-------------");
try {
String transId = (String)msg.getHeaders().get(RocketMQHeaders.PREFIX + RocketMQHeaders.TRANSACTION_ID);
String orderId = String.valueOf(arg);
TransactionLog transactionLog = new TransactionLog();
transactionLog.setTransactionId(transId);
transactionLog.setBusiness("生成订单");
transactionLog.setForeignKey(orderId);
transactionLogService.insert(transactionLog);
return RocketMQLocalTransactionState.COMMIT;
} catch (Exception e) {
log.error("创建rocketMQ下单事务消息失败,原因:{}",e);
return RocketMQLocalTransactionState.ROLLBACK;
}
}
/**
* 下单事务回查,事务状态回查最大次数transactionCheckMax 默认15次,每次回查的间隔时间transactionTimeOut 默认6秒。检查10次,模拟一分钟支付时间
* @param message
* @return
*/
//本地事务检查,检查本地事务是否成功
@Override
public RocketMQLocalTransactionState checkLocalTransaction(Message message) {
//获取事务ID
String transId = (String)message.getHeaders().get(RocketMQHeaders.PREFIX + RocketMQHeaders.TRANSACTION_ID);
log.info("检查本地事务,事务ID:{}", transId);
//根据事务id从日志表检索
TransactionLog transactionLog=transactionLogService.findByTransactionId(transId);
if (null != transactionLog) {
return RocketMQLocalTransactionState.COMMIT;
}
return RocketMQLocalTransactionState.ROLLBACK;
}
}
用户服务
@Slf4j
@Component
@RocketMQMessageListener(consumerGroup = "ums-group", topic = "${rocketmq.tulingmall.asyncOrderTopic}")
public class RocketMqCreateOrderReciever implements RocketMQListener<String> {
/**
* 延时消息,取消超时订单
* @param message orderId:memberId
*/
@Override
public void onMessage(String message) {
if(StringUtils.isEmpty(message)){
return;
}
Long orderId = Long.parseLong(message.split(":")[0]);
Long memberId = Long.parseLong(message.split(":")[1]);
try {
log.info("-----------------执行扣除用户积分------------");
} catch (Exception e) {
log.error("订单取消异常 : 还原库存失败,please check:{}",e.getMessage(),e.getCause());
throw new RuntimeException();//抛异常出去,rocketmq会重新投递
}
}
}
商品服务
@Slf4j
@Component
@RocketMQMessageListener(consumerGroup = "pms-group", topic = "${rocketmq.tulingmall.asyncOrderTopic}")
public class RocketMqCreateOrderReciever implements RocketMQListener<String> {
/**
* 延时消息,取消超时订单
* @param message orderId:memberId
*/
@Override
public void onMessage(String message) {
if(StringUtils.isEmpty(message)){
return;
}
int i=1/0;
Long orderId = Long.parseLong(message.split(":")[0]);
Long memberId = Long.parseLong(message.split(":")[1]);
try {
log.info("-----------------执行扣除库存------------");
} catch (Exception e) {
log.error("订单取消异常 : 还原库存失败,please check:{}",e.getMessage(),e.getCause());
throw new RuntimeException();//抛异常出去,rocketmq会重新投递
}
}
}