在后面的文章中,咱们介绍了分布式事务的概念以及一些解决方案。fenSeata是一款开源的分布式事务解决方案,致力于提供高性能和简略易用的分布式事务服务。Seata将为用户提供了AT、TCC、SAGA和XA事务模式,为用户打造一站式的分布式解决方案。
Seata介绍
本文以一个用户下单购买商品的零碎为例,介绍开源框架Seata的原理和应用,下单该零碎波及三局部服务:
- 仓储服务:对给定的商品扣除仓储数量;
- 订单服务:依据洽购需要创立订单;
- 帐户服务:从用户帐户中扣除余额;
分布式事务的次要作用是保障微服务状况下用户下单过程中数据的一致性。这里的一致性能够这样了解:不会呈现用户余额扣除胜利,然而仓储和订单相干操作失败的场景,三者要么同时胜利,要么同时失败。
单机事务场景
如果用户下单购买商品波及到的服务都在一个传统的单机服务中,三局部服务能够共享同一个数据库实例。这种状况下,咱们能够通过本地事务的一致性保障仓储/订单/账户三者之间数据的一致性。
如上图所示,在单机服务中,三局部内容共用同一个数据库实例,所以咱们只须要本地事务就能够解决数据的一致性,以Spring框架为例,咱们只须要在办法上增加@Transaction
注解就能够实现整个购买流程中数据的一致性:
@Transactionpublic void purchase(){ doStoreBusiness(); doOrderBusiness(); doAccountBusiness();}
分布式事务场景
在微服务框架中,仓储/订单/账户服务部署在不同的服务器上,应用不同的数据库实例,与单机模式齐全不同。单机模式中的事务通常要求事务波及的数据源为同一个,并且事务波及的数据库操作在同一个数据库链接中,分布式状况下显然不满足条件。
所以在分布式场景如何保证数据的一致性呢?这就是Seata须要解决的问题了。
Seata解决方案
Seata是用于解决分布式事务的开源框架,其外部有对于分布式事务的定义如下:分布式事务是由多个分支事务组成的全局事务,其中每个分支事务都是本地事务的模式。
Seata框架蕴含三局部内容:
- 事务协调器(Transaction Coordinator,TC):保护全局事务和分支事务的状态,进行全局事务提交或全局事务回滚;
- 事务管理器(Transaction Manager,TM):定义全局事务,开启全局事务、提交全局事务或回滚全局事务;
- 资源管理器(Resource Manager,RM):治理分支事务中的资源,向事务管理器注册分支事务和并报告分支事务的状态,负责分支事务提交或回滚;
一个典型的seata分布式事务的流程如下:
- TM向TC收回开启全局事务申请,TC生成全局事务的惟一标识XID,设此处的全局事务为T1;
- 在全局事务T1的各个流程中,XID会作为事务的标识在微服务之间流转;
- RM向TC注册本地事务,注册的本地事务的会作为全局事务T1的分支事务;
- TM能够申请TC管制全局事务T1提交或全局事务T1回滚;
- TC能够申请全局事务T1下的所有分支事务提交或回滚;
Seata历史
阿里巴巴:
- TXC:淘宝交易系统的分布式事务框架,阿里巴巴中间件团队自2014年开始启动该我的项目,用于解决利用架构从繁多服务向微服务转变所带来的分布式事务问题;
- GTS:寰球交易服务。TXC作为阿里云中间件产品,新名称GTS于2016年公布;
- Fescar:2019年开始了基于TXC/GTS的开源我的项目Fescar,用于开源我的项目社区倒退;
蚂蚁金服:
- XTS:扩大事务服务。蚂蚁金服中间件团队自2007年开始开发分布式事务中间件,该中间件在蚂蚁金服中失去广泛应用,解决了跨数据库和服务的数据一致性问题。
- DTX:分布式事务扩大。自2013年以来,XTS已在蚂蚁金融云上公布,名称为DTX;
Seata社区:
- Seata:简略的可扩大分布式事务解决方案,蚂蚁金服将Fedscar改名为Seata并开源,使其成为一个中立、凋谢的分布式事务社区。
Seata Maven依赖
<seata.version>1.4.2</seata.version><dependency> <groupId>io.seata</groupId> <artifactId>seata-all</artifactId> <version>${seata.version}</version></dependency>
Seata案例
以上文中的用户下单购买商品的零碎为例,展现Seata的应用形式:
- 仓储微服务:对给定的商品扣除仓储数量;
- 订单微服务:依据洽购需要创立订单;
- 帐户微服务:从用户帐户中扣除余额;
服务接口的定义
对于三个微服务,咱们用三个接口来形象其外部的逻辑:
仓储服务
public interface StorageService { /** * 扣除存储数量 */ void deduct(String commodityCode, int count); }
订单服务
public interface OrderService { /** * 创立订单 */ Order create(String userId, String commodityCode, int orderCount); }
帐户服务
public interface AccountService { /** * 从用户账户中借出 */ void debit(String userId, int money);}
次要业务逻辑
对于用户下单购买商品的逻辑,咱们用以下代码来实现:
次要业务逻辑
public class BusinessServiceImpl implements BusinessService { private StorageService storageService; private OrderService orderService; /** * 洽购 */ public void purchase(String userId, String commodityCode, int orderCount) { storageService.deduct(commodityCode, orderCount); orderService.create(userId, commodityCode, orderCount); } }
订单服务业务逻辑
public class OrderServiceImpl implements OrderService { private OrderDAO orderDAO; private AccountService accountService; public Order create(String userId, String commodityCode, int orderCount) { int orderMoney = calculate(commodityCode, orderCount); accountService.debit(userId, orderMoney); Order order = new Order(); order.userId = userId; order.commodityCode = commodityCode; order.count = orderCount; order.money = orderMoney; // INSERT INTO orders ... return orderDAO.insert(order); } }
引入Seata
在服务中引入Seata服务之后,咱们只须要在分布式事务最外层的办法上增加分布式事务注解@GlobalTransactional
:
@GlobalTransactionalpublic void purchase(String userId, String commodityCode, int orderCount) { // ......}
增加注解之后,在执行业务逻辑之前,Seata会学生成全局事务ID,并且在调用其它服务时,会在申请中携带全局事务ID。如果其它微服务也增加了Seata依赖,这些微服务会获取全局事务ID,并且参加到全局事务中。
本文只是简略介绍以下Seata框架,具体工作原理在后续文章中具体介绍。
我是御狐神,欢送大家关注我的微信公众号:wzm2zsd
参考文档
Seata官网文档
本文最先公布至微信公众号,版权所有,禁止转载!