在后面的文章中,咱们介绍了分布式事务的概念以及一些解决方案。fenSeata 是一款开源的分布式事务解决方案,致力于提供高性能和简略易用的分布式事务服务。Seata 将为用户提供了 AT、TCC、SAGA 和 XA 事务模式,为用户打造一站式的分布式解决方案。
Seata 介绍
本文以一个用户下单购买商品的零碎为例,介绍开源框架 Seata 的原理和应用,下单该零碎波及三局部服务:
- 仓储服务:对给定的商品扣除仓储数量;
- 订单服务:依据洽购需要创立订单;
- 帐户服务:从用户帐户中扣除余额;
分布式事务的次要作用是保障微服务状况下用户下单过程中数据的一致性。这里的一致性能够这样了解:不会呈现用户余额扣除胜利,然而仓储和订单相干操作失败的场景,三者要么同时胜利,要么同时失败。
单机事务场景
如果用户下单购买商品波及到的服务都在一个传统的单机服务中,三局部服务能够共享同一个数据库实例。这种状况下,咱们能够通过本地事务的一致性保障仓储 / 订单 / 账户三者之间数据的一致性。
如上图所示,在单机服务中,三局部内容共用同一个数据库实例,所以咱们只须要本地事务就能够解决数据的一致性,以 Spring 框架为例,咱们只须要在办法上增加 @Transaction
注解就能够实现整个购买流程中数据的一致性:
@Transaction
public 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
:
@GlobalTransactional
public void purchase(String userId, String commodityCode, int orderCount) {// ......}
增加注解之后,在执行业务逻辑之前,Seata 会学生成全局事务 ID,并且在调用其它服务时,会在申请中携带全局事务 ID。如果其它微服务也增加了 Seata 依赖,这些微服务会获取全局事务 ID,并且参加到全局事务中。
本文只是简略介绍以下 Seata 框架,具体工作原理在后续文章中具体介绍。
我是御狐神,欢送大家关注我的微信公众号:wzm2zsd
参考文档
Seata 官网文档
本文最先公布至微信公众号,版权所有,禁止转载!