阿里面试官:RocketMQ与Kafka中如何实现事务?

本文已收录GitHub,更有互联网大厂面试真题,面试攻略,高效学习资料等

RocketMQ的事务是如何实现的?

首先我们来看 RocketMQ 的事务。我在之前的课程中,已经给大家讲解过 RocketMQ 事务的大致流程,这里我们再一起通过代码,重温一下这个流程。

public class CreateOrderService {
	@Inject
	private OrderDao orderDao;
	//注入订单表的DAO
	@Inject
	private ExecutorService executorService;
	//注入一个ExecutorService
	private TransactionMQProducer producer;
	//初始化transactionListener和producer
	@Init
	public void init() throws MQClientException {
		TransactionListener transactionListener = createTransactionListener();
		producer = new TransactionMQProducer("myGroup");
		producer.setExecutorService(executorService);
		producer.setTransactionListener(transactionListener);
		producer.start();
	}
	//创建订单服务的请求入口
	@PUT
	@RequestMapping(...)
	public Boolean createOrder(@RequestBody CreateOrderRequest request) {
		//根据创建订单请求创建一条消息
		Message msg = createMessage(request);
		//发送事务消息
		SendResult sendResult = producer.sendMessageInTransaction(msg, request);
		//返回:事务是否成功
		return sendResult.getSendStatus() == SendStatus.SEND_OK;
	}
	private TransactionListener createTransactionListener() {
		return new TransactionListener() {
			@Override
			public LocalTransactionState executeLocalTransaction(Message msg, Object arg) {
				CreateOrderRequest request = (CreateOrderRequest ) arg;
				try {
					//执行本地事务创建订单
					orderDao.createOrderInDB(request);
					//如果没抛异常说明执行成功,提交事务消息
					return LocalTransactionState.COMMIT_MESSAGE;
				}
				catch (Throwable t) {
					//失败则直接回滚事务消息
					return LocalTransactionState.ROLLBACK_MESSAGE;
				}
			}
			//反查本地事务
			@Override
			public LocalTransactionState checkLocalTransaction(MessageExt msg) {
				//从消息中获得订单ID
				String orderId = msg.getUserProperty("orderId");
				//去数据库中查询订单号是否存在,如果存在则提交事务;
				//如果不存在,可能是本地事务失败了,也可能是本地事务还在执行,所以返回UNKNOW//(PS:这里RocketMQ有个拼写错误:UNKNOW)
				return orderDao.isOrderIdExistsInDB(orderId)?
				LocalTransactionState.COMMIT_MESSAGE: LocalTransactionState.UNKNOW;
			}
		}
		;
	}
	//....
}

在这个流程中,我们提供一个创建订单的服务,功能就是在数据库中插入一条订单记录,并发送一条创建订单的消息,要求写数据库和发消息这两个操作在一个事务内执行,要么都成功,要么都失败。在这段代码中,我们首先在 init() 方法中初始化了 transactionListener和发生 RocketMQ 事务消息的变量 producer。真正提供创建订单服务的方法是createOrder(),在这个方法里面,我们根据请求的参数创建一条消息,然后调用RocketMQ producer 发送事务消息,并返回事务执行结果。

之后的 createTransactionListener() 方法是在 init() 方法中调用的,这里面直接构造一个匿名类࿰

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值