开发者学堂课程【全面讲解Spring Cloud Alibaba技术栈(知识精讲+项目实战)第五阶段:Seata案例-Seata使用】学习笔记,与课程紧密联系,让用户快速学习知识。
课程地址:https://developer.aliyun.com/learning/course/687/detail/11930
Seata案例-Seata使用
内容介绍
一、前言和总述
二、seata 的基本介绍
三、初始化 seata 在 nacos 中的配置
四、启动 Seata 服务
五、使用 Seata 实现全局控制
一、前言和总述
通过异常模拟的方式发现了在当前的分布式系统中事务是无法控制的,接下来就要利用 seata 去解决这个问题。
二、seata的基本介绍
1、服务端
其实 seata 的服务端也称作 seata 的 server,指的就是TC事务协调器。事务协调器是一个非常重要的组件,它用于管理全局事务的提交或回滚,在 seata 中是单独进行的一个应用。只需要把它下载下来,修改对应的配置然后启动就可以了。
2、下载地址
首先 seata 下载地址为https://github.com/seata/seata/releases/v0.9.0/这是 seata 在 github 上的地址,其中有对应的格式。在此已经准备好了一个zip格式的,直接使用就可以。把 seatasever 复制到工作空间中,对 zip 格式的压缩包进行解压到当前的文件夹中。解压后出现了一个 seata 的文件夹,原有的压缩包就删除了。
3、配置
修改 seata 的一些配置,主要修改的有两个文件。
(1)registry.conf
对其是修改注册和配置的指定。
①注册中心
它支持的注册中心有文件、nacos、eureka、redis、consul 等很多类型。默认的注册中心为软件。现在已经学习过 nacos,而且是阿里巴巴技术站中的内容。所以要优先考虑使用 nacos,也就是要把默认的注册中心改为 nacos。
②控制中心
同样它的控制中心也支持 file、nacos、apollo 这些内容,默认的控制中心同样为 nacos。指定的就是本机的命名空间是 namespace,默认空间为public。Cluster 集群使用的是 default。基本上均是默认配置,只需指定一个nacos就可以了。
(2)nacos-config.txt
对第二个配置文件进行修改,在当前文件夹之下有一个nacos-config.txt,其中存在着许多的配置,但需要调整的只有一个地方。但是微服务中还未配置,首先要配置好,等一下配置微服务时与其保持一致就可以了。
前面的 service.vgroup_mapping 不能变动,后面的 default 也不能改动,只需要对中间部分的 product-service 进行改动。中间部分使用的就是微服务的名称,只要牢记在微服务中配置项的时候与product-service 保持一致就可以了。这就是需要进行调整的两个配置,这两个配置调整之后接下来就是启动 seata。
三、初始化seata在nacos中的配置
在启动 seata 之前,首先要把 seata 中的一批数据初始化到注册中心中,它提供了一个脚本为 nacos-config.sh127.0.0.1,对此需要保证 nacos 是正常运行的。nacos 中的配置,找到配置列表后发现其中是空白的。接下来对其进行初始化,然后运行 nacos-config.sh,会发现它在做一些脚本的初始化。初始化完毕后再次进行刷新,会发现出现了大量的配置项。这些配置项均是 seata 内置所要用到的东西。主要关注的其实就是刚才所填写的配置的名称,即service.vgroup_mapping.product-service 和service.vgroup_mapping.order-service。这个只要正确就说明刚才的配置文件没有问题。它们的分组均是SEATA_GROUP。这样的话在初始化中 nacos 的配置就成功了。
四、启动Seata服务
启动 seata 之后也会注册到nacos中,在 nacos 的服务列表中可以看到一个名为 serverAddr 的服务,这个服务在目前为止是不存在的。
启动的命令是 seata-sever.bat-p-mfile,p 指的是端口,监听在9000端口上。这个端口号可以随便写,只要不重复就可以。mfile就成为一个模式,对其直接使用就可以了。等待它启动完毕之后会在 nacos 中注册一个服务,再次刷新就会发现有一个 serverAddr,默认分组的名称为 DEEAULT_GROUP。只要看到 serverAddr 就证明 seata-sever 是启动成功的,不存在任何的问题。至此事务协调器已经准备完毕了。接下来就在应用中添加 TM 以及 RM,两者是以一个依赖包的形式加入到服务中的。
在使用 seata 实现事务的控制中有一个初始化的数据表,这张数据表其实是用于记录 undo_logo 日志的。
五、使用Seata实现全局控制
1、初始化数据表
(1)文字讲解
现在开启全局服务,在下单完成之后,会将本地事务提交上去,在数据库之中就已经存在这条日志了。
在日志存在以后,当商品微服务后面后面的半只服务出现问题时是无法回滚的。所以 undo_logo 日志就是用来记录事务本身的操作。事务操作之前和之后分别为什么样子均记录下来。一旦发现后面的半只事务出现问题了,立刻按照 undo_logo 日志中的内容进行回滚。把 undo_logo 日志打开,其中有分支事务ID、全局事务ID以及回滚的信息等等。
(2)代码如下:
CREATETABLEundo_log
"id'BIGINT(20)NOTNULLAUTO_INCREMENT,
branch_idBIGINT(20)NOTNULL,
xidVARCHAR(100)NOTNULL,
contextVARCHAR(128)NOTNULL,
rollback_infolongBloBNOTNULL,
log_statusINT(11)NOTNULL,
log_created`DATETIMENOTNULL,
loq_modified`DATETIMNOTNULL.
'extVARCHAR(100)DEFAULTNULL,
PRIMARYKEY('id'),
UNIQUEKEY'ux_undo_1og’(`xid',"branch_id')
ENGINE=INNODB
AUTO_INCREMENT=1
DEFAULTCHARSET=utf8
接下来是对各个微服务的修改。对微服务的修改主要包括一下几个内容。
2、添加配置
(1)添加依赖
这个依赖就认为是 TM 和 RM 的所在包就可以了。三个组件分别为TC、TM 和 RM。TC是以单独的应用执行的,而 TM 和 RM 均是在这样的依赖包中的。
代码如下:
com.alibaba.cloud
spring-cloud-starter-alibaba-seata
(2)DataSourceProxyConfig
第二部分要配置一个代理数据源,seata 是通过代理数据源来实现事务分支的,如果不提供它则是无法进行事务回滚操作的,所以需要配置 io.seata.rm.datasource.DataSourceProxy 的 Bean。以下所使用的是德鲁伊的数据源所代理出的。
在两个微服务中同样需要加入 config 这样的包,然后在此下面创建一个类,这个类的内容对以下的代码直接进行复制即可。这就是一个代理的数据源,对此还需要导入 seata 提供的一个包就可以了。此外有一个 spring.Datasource 的前缀,这里一定是和 resources 下的 application.yml 相对应的。
代码如下:
@Configuration
publicclassDataSourceProxyConfig{
@Bean
@ConfigurationProperties(prefix=“spring.datasource”)public
DruidDataSourcedruidDataSource(){
returnnewDruidDataSource();}
@Primary
@Bean
publicDataSourceProxydataSource
(DruidDatasourcedruidDatasource)
returnnewDataSourceProxy(druidDataSource);
(3)registry.conf
接下来就是把方才所需要配置的 registry.conf 放置在微服务中,因为微服务也是需要从 nacos 中引用内容的。对此直接进行复制,放到 resources 下面的一个新的文件,它的内容与方才所用的seata下面的 conf 是相同的,它是去寻找与之相对应的 nacos 的。
代码如下:
registry{
type="nacos"
nacos{
serverAddr="localhost"
namespace="public"
cluster="default"
}
config{
type="nacos"
nacos{
serverAddr="localhost"
namespace="public"
cluster="default"
(4)bootstrap.yaml
这里面最重要的内容只有两点,第一个是指定读取 nacos 中的配置,因为在 TC 中已经预支了很多的配置机理。
下面还有一个 seata 的 service 的分组,需要注意的是这个分组要和前面的 order-service 保持一致。
如果两者不相同,则是无法找到它的分组,也就无法对其进行控制了。Namespace 所用的是public,group所用的是 SEATA_GROUP,与配置列表中的 SEATA_GROUP 相对应。需要注意的是 product-service指的是service-product。
最终要保持相同的是两个 product-service,只不过默认的是二者均和 service-product 保持一致。
代码如下:
spring:
application:
name:service-product
cloud:
nacos:
config:
server-addr:localhost:8848#nacos的服务端地址namespace:
public
group:SEATAGROUP
alibaba:
seata:
tx-service-group:product-service
3、在 order 中开启全局事务
如果要处理全局事务仅需要一个注解 GlobalTransactional 就可以解决。要找到需要开启的地方并把注解填进去。找到下订单要执行的方法,把 GlobalTransactional 代入即可。只需要这样一个注解,没有其他的任何代码。Seata 执行的是没有代码的侵入性原则,这里就与其相对应。
分别来启动 order 和 product,等到启动完毕之后重新下一个订单看会出现什么情况。现在是有两个订单,库存为4999。把库存恢复成5000后进行刷新,再把 order全部删除,这样的话测试起来就顺利一些了。现在两个服务均已经启动了,通过 nacos 对其是可以进行监听。再次来看一下执行流程。保存之后需要把断点了解一下,之前需要确认一下 product 是有断点的。在此看一下数据库了解情况。首先看一下 order 的表格,看是否有保存的订单。会发现方才已经提交了,但现在又被回滚了,因为在此有一个时间的限制。重新再做一次下单,在经过一个断点之后会发现在 undo.logo 中已经有日志了。
日志中最重要的内容是在进行回滚的时候需要用到的一些信息,会记录一些原始的状态。
其中记录了原本的值,如果出现问题时就按照这个值进行回滚。一旦出现异常就按照相关的规则进行回滚了。
在刷新后是没有订单的,库存也是未扣除,就不存在问题了。