dawdler-distributed-transaction
模块介绍
分布式事务模块的根模块.
分布式事务架构原理
分布式事务有三种状态: trying(尝试中),confirm(已确认),cancel(取消).
发起者通过以下4个步骤完成分布式事务的处理:
1、通过@DistributedTransaction标识为分布式事务的发起者与参与者.
2、通过aop拦截@DistributedTransaction,发起者生成全局事务id及上下文.
3、发起者调用参与者,通过aop拦截到@DistributedTransaction标识的参与者,生成分支事务id及trying状态信息并序列化到redis中.调用具体的参与者服务,如果执行出现异常则标识事务回滚并抛出异常.
4、执行过程中发起者调用参与者出现异常或自定义的TransactionInterceptInvoker标识事务为cancel状态,将redis中存储的事务标识为cancel状态并进行事务回滚(发送mq消息).如果参与者全部执行完成(没有被标识为回滚状态)则将redis中存储设 为confirm状态并进行事务提交(发送mq消息).
补偿器模块
1、消费到发起者发送过来的消息后执行对应的业务方法(注意:需要实现幂等),执行成功后会删除redis存储的对应的分支事务信息.
2、定时补偿器会定期执行指定时间范围的事务,防止mq消费后执行失败的事务不再执行(一般为服务宕机或网络不可用).
1. web端的pom中引入依赖
<groupId>club.dawdler</groupId>
<artifactId>dawdler-distributed-transaction-client</artifactId>
2. dawdler服务端的pom中引入依赖
<groupId>club.dawdler</groupId>
<artifactId>dawdler-distributed-transaction-server</artifactId>
3. web端补偿器模块的pom中引入依赖
<groupId>club.dawdler</groupId>
<artifactId>dawdler-distributed-transaction-compensator</artifactId>
4. 使用方式
4.1 配置分布式事务
将需要加入分布式事务管理的服务进行配置,分布式事务分为发起者与参与者.
根据业务定义服务,将web接口设置为事务发起者,服务的接口设为参与者.
举例 下订单的一个业务中,有以下3个服务(具体可以参考示例):
4.1.1 订单服务
api层定义接口
//订单服务的接口定义
@Service("distributed-transaction-order-service")
public interface OrderService {
@DistributedTransaction(action = "order",sponsor = false)//标识为分布式事务的参与者
public boolean createOrder(Integer userId, Integer productId, BigDecimal amount);
public boolean updateStatusOrder(DistributedTransactionContext context, String status);
}
.
4.1.2 用户服务
api层定义接口
//用户服务的接口定义
@Service("distributed-transaction-user-service")
public interface UserService {
@DistributedTransaction(action = "user",sponsor = false)//标识为分布式事务的参与者
public Map<String, Object> tryPayment(Integer userId,BigDecimal amount);
public boolean doPayment(DistributedTransactionContext context, String status);
}
4.1.3 商品库存服务
api层定义接口
//商品库存服务的接口定义
@Service("distributed-transaction-product-service")
public interface ProductService {
@DistributedTransaction(action = "product",sponsor = false)//标识为分布式事务的参与者
public Map<String, Object> tryDeductStock(Integer productId, Integer stock);
public boolean doDeductStock(DistributedTransactionContext context,String status);
}