1、问题背景
微服务架构中,随着业务的拆分,数据库必然跟着业务拆分,分库,分表;跨库跨服务必然会引发事务问题;导致不同服务的数据一致性问题
2、seata介绍
seata 是开源的分布式事务解决方案,致力于微服务架构下提高性能和简单易用的分布式事务服务;
seata 服务主要由3部分组成
下面斜体的是我自己对官方的话的一个解释
TC - 事务协调者
维护全局和分支事务的状态,驱动全局事务提交或回滚。
事务协调者,可以理解为seata-server, 也就是seata的服务端
TM - 事务管理器
定义全局事务的范围:开始全局事务、提交或回滚全局事务。
事务管理器,就是 事务发起方,比如下面的示例事务管理者就是business, 一般加
@GlobalTransactional
注解
RM - 资源管理器
管理分支事务处理的资源,与TC交谈以注册分支事务和报告分支事务的状态,并驱动分支事务提交或回滚。
事务的参与者,如下示例的
Storage
,Order
,Account
, 这些服务不需要加注解,但是项目需要做一些配置,下面会进一步讲解
对于上面多的概念,可能很难理解,下面用官方的示例说明一下
- 秒杀服务(Business): 发起也对个服务的调用
- 仓储服务(Storasge):对给定的商品扣除仓储数量。
- 订单服务(Order):根据采购需求创建订单。
- 帐户服务(Account):从用户帐户中扣除余额。
3 、 整体机制
seata做了什么, 下面是
AT
模式的说明
- 一阶段:业务数据和回滚日志记录在同一个本地事务中提交,释放本地锁和连接资源。
- 二阶段:
- 提交异步化,非常快速地完成。
- 回滚通过一阶段的回滚日志进行反向补偿。
4、seata接入方式
使用的是
AT
模式
4.1
,4.2
, 是所有参与事务的服务都需要引用的
4.1 引包
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-seata</artifactId>
</dependency>
<dependency>
<groupId>io.seata</groupId>
<artifactId>seata-spring-boot-starter</artifactId>
<version>1.1.0</version>
</dependency>
4.2 改yml
# 数据库的配置示例
spring:
jackson:
date-format: yyyy-MM-dd HH:mm:ss
time: GMT+8
application:
name: demo-geek-order
datasource:
type: com.alibaba.druid.pool.DruidDataSource
druid:
url: jdbc:mysql://xxx:3306/xxx?characterEncoding=utf8&useSSL=false&serverTimezone=GMT%2B8&rewriteBatchedStatements=true&allowPublicKeyRetrieval=true
username: xxx
password: xxx
max-active: 20
min-idle: 2
driver-class-name: com.mysql.cj.jdbc.Driver
cloud:
nacos:
discovery:
server-addr: xxx:8848
namespace: 82632dc2-fce3-4288-b49e-9d270643df74
# seat 配置
seata:
enabled: true
tx-service-group: my_test_tx_group
enable-auto-data-source-proxy: true
application-id: ${spring.application.name}
config:
type: nacos
nacos:
group: SEATA_GROUP
server-addr: xxx.5:8848
namespace: 82632dc2-fce3-4288-b49e-9d270643df74
registry:
type: nacos
nacos:
cluster: default
server-addr: xxx.5:8848
namespace: 82632dc2-fce3-4288-b49e-9d270643df74
4.3 配置事务管理器- 事务发起方
添加注解: @GlobalTransactional(timeoutMills = 50000, name = "prex-create-order")
- timeoutMills : 超时时间
- name: 事务组
@GlobalTransactional(timeoutMills = 50000, name = "prex-create-order")
public void createOrder(OrderReq order) throws Exception {
}