一站式分布式事物解决方案 seata

    之前我们聊完了分布式框架spring cloud,今天我们来聊下由分布式应用带来的问题,分布式事物。

什么是分布式事物,这里摘录一段分布式事物定义:

提起分布式事务,最早指的涉及多个资源的数据库事务问题。

wiki对分布式事务的定义:

Adistributed transaction is a database transaction in which two or more networkhosts are involved.

不过事务一词含义随着SOA架构逐渐扩大,根据上下文不同,可分为两类:

  1. Systemtransaction

    2.Businesstransaction

前者多指数据库事务,后者则多对应一个业务交易。与此同时,分布式事务的含义也在泛化,

尤其SOA、微服务概念流行起来后,多指的是一个业务场景,需要编排很多独立部署的服务时,

如何保证交易整体的原子性与一致性问题,这类分布式事务也称作长事务(long-livedtransaction),

例如一个定行程的交易,它由购买航班、租车以及预订酒店构成,而航班预订可能需要一两天才能确认。

为了统一对概念的理解,本文默认指的都是这类长事务。

 

    目前市面上已经有很多解决方案:TCC,SAGA,XA, SEATA等。TCC 方案有

ByteTCC、TCC-transaction、EasyTransaction等,SEATA也支持TCC模式,之所以说seata 是分布式事物一站式解决方案,是因为他集成了TCC,SAGA,XA(规划中)等方案。笔者之前也调研了一部分TCC框架,经过试验和组内反馈,使用是没有问题,但是TCC 方案对业务侵入太大,所谓TCC 也就是 try-confirm-catch ,原本一个动作需要拆分成三个逻辑接口,即资源申请冻结接口,确认操作接口,以及try接口失败的回滚接口。可以看到此方案对业务需要进行业务改造,当然也有优点,对数据库等资源没有使用锁等机制。

 

那么seata又是如何来解决的呢,我们先来看一张图片以及名词术语结束:

Seata术语

TC - 事务协调者

维护全局和分支事务的状态,驱动全局事务提交或回滚。

TM - 事务管理器

定义全局事务的范围:开始全局事务、提交或回滚全局事务。

RM - 资源管理器

管理分支事务处理的资源,与TC交谈以注册分支事务和报告分支事务的状态,并驱动分支事务提交或回滚。

从图中我们可以看到 seata 将 事物TC(事物协调者)独立出来部署了。

结合上面的图示,说下seta框架的大致思路:

 

1.业务层发起远程服务调用时,首先向TC注册全局事务。

2.远程服务调用被调用时,先向TC注册分支事物(分支事物的ACID由本地事物提供保障),并且会向tc汇报分支事物的状态。

3.当所远程服务执行成功后会提交本地事务。

4,远程服务执行失败或者超时等,TC 会向所有RM 发起本地事物回滚指令,进行全局回滚。(如何回滚,当提交本地事物的时候,seata 会生成本地回滚sql 的镜像sql 存储至undo_log 表)

以上是seata 的大致流程思路,详细流程可以参考官方文档:

http://seata.io/zh-cn/docs/overview/what-is-seata.html

 

下面我们开始搭建seata 环境:

首先搭建seata server;下载地址:

http://seata.io/zh-cn/blog/download.html

当然也可以从git 自行下载最新版本:https://github.com/seata/seata

如果是从git拉取代码,启动server 之前需要先执行命令:

mvn clean install -DskipTests=true -U

打包命令:mvn clean install -DskipTests=true -U -P release-seata

如果是下载源码启动服务,只需要找到seata-server 目录下的Server 类右击run就可以了。如图

 

默认配置是file模式。即所有的全局事物,所信息等都是本次存储。

当然也可以修改file.conf 配置,修改为数据库存储(目前seata 支持 mysql 和oracle)

默认配置file  模式启动看到如下日志表示seata server 启动成功:

另外如果是需要以db形式存储,需要现在数据库执行相关脚本:

脚本在seata server resource 下:

默认是mysql版本的脚本,其他数据库可自行修改。

下面我们来运行官方提供的demo,官方提供了很多版本的demo,demo地址:https://github.com/seata/seata-samples

 

我们下载demo后,找到dubbo版本的demo:

具体运行什么demo,小伙伴们可以自行根据自己的兴趣选择。

需要使用seata ,需要添加maven依赖:

<seata.version>0.9.0</seata.version>
<dependency>
    <groupId>io.seata</groupId>
    <artifactId>seata-all</artifactId>
    <version>${seata.version}</version>

</dependency>

当然此处有一个小坑,seata 对jackson 的最低版本是2.9.9。

 

 

我们依次启动相应的dubbo 服务:

找到上图的dubbo 服务启动入口然后启动;

如果启动服务时碰到如下异常:

请关闭qos启动,这是一个dubbo 在线运维服务,详细参考:

https://blog.csdn.net/u012988901/article/details/84503672

修改配置即可:

 

官方实例也就是常见的分布式电商系统交易场景,当然实际场景比这个复杂很多,如图:

业务层进行下单请求,分别会调用库存服务进行库存减少,调用订单服务进行下单,订单服务会调用账户服务,进行金额扣减操作。

如果你直接跑这个demo,需要自行准备dubbo的注册中心,以及运行demo

的sql脚本:

dubbo_biz.sql 是业务表,undo_log.sql 是业务库回滚日志表,不同的业务库都需要建立 undo_log表,如果所有服务使用同一个数据库,只需要建立一个就行。

另外业务系统的数据源必须被seata 代理DataSourceProxy(datasource);

这里要敲黑本,划重点。

下面我们来看下代码:

先看业务才能调用:

继续跟踪代码:

这里分别调用了库存服务和订单服务,并且我们看到了,方法上加了一个注解:

@GlobalTransactional(timeoutMills = 300000, name = "dubbo-demo-tx")

这个注解的作用是开启seata 全局事物,在我们使用seata 的过程当中,我们唯一需要使用的也就是这一个注解。他就能帮我们搞定所有的分布式事物问题。

这里有小伙伴可能会有疑问,远程服务是如何感知全局事务,注册分支事物的呢,以dubbo 为例,当我们使用@GlobalTransactional 开启全局事物时,调用dubbo服务,seata会在dubbo框架层面传参数XID(透明传参,开发者无需关心),当服务被调用,框架感知到XID 时会进行本地分支事物的注册以及状态汇报等,这些框架层面会帮我们处理掉,这样就可以说是对业务实现零侵入。

这里不再列出demo运行实例,感兴趣的小伙伴可以自行动手运行官方demo。

 

注意事项:

1,seata 目前最新版本0.9.0 (2019-11,预计12月份发布1.0.0版本),数据库oracle 字段不支持 timestamp, 序列化不支持

2,表结构必须有主键,索引

3,每个业务库都必须建立 undo_log 表。

4,数据源必须被seata代理: new DataSourceProxy(datasource);

目前seata 最新版本为 0.9.0.1, 1.0Release 版本预计十二月份就会发布,期待ing。。。。

最后附上seata 官方文档地址:http://seata.io/zh-cn/docs/overview/what-is-seata.html

 

以及官方讨论群:(钉钉群),感兴趣的小伙伴可以添加。

 

本文对seata讲解到此结束,如有不对之处,欢迎指正交流!

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值