事务消息是 RocketMQ 的高级特性之一 。这篇文章,笔者会从应用场景、功能原理、实战例子三个模块慢慢为你揭开事务消息的神秘面纱。
1 应用场景
举一个电商场景的例子:用户购物车结算时,系统会创建支付订单。
用户支付成功后支付订单的状态会由未支付修改为支付成功,然后系统给用户增加积分。
通常我们会使用普通消费方案,该方案能够发挥 MQ 的优势:异步和解耦 , 同时架构设计非常简单。
-
用户购物车结算时,系统创建支付订单;
-
支付成功后,更新订单的状态从未支付修改为支付成功;
-
发送一条普通消息到消息队列服务端;
-
积分服务消费消息,添加积分记录。
但该方案有个非常直观的缺点:容易出现不一致的现象。
-
假如先发送消息,后修改订单状态,消息发送成功,订单没有执行成功,需要回滚整个事务(订单数据事务回滚,积分服务消费时,需要先反查事务状态,若事务提交,才能插入积分记录)。
-
假如先修改订单状态,后发送消息,订单状态修改成功,但消息发送失败,需要补偿操作才能保持最终一致。
-
假如先修改订单,后发送消息,订单状态修改成功,但消息发送超时,此时无法判断需要回滚订单还是提交订单变更。
我们看到,为了完善普通消费方案,业务层还需要做到两点:补偿机制和提供事务状态查询接口。
要做到这两点,难不难呢?
不难,但是业务层代码会比较混乱