1. 首先了解什么是seata?
Seata 是一款开源的分布式事务解决方案,致力于在微服务架构下提供高性能和简单易用的分布式事务服务。
2019 年 1 月,阿里巴巴中间件团队发起了开源项目 Fescar(Fast & EaSy Commit And Rollback),和社区一起共建开源分布式事务解决方案。Fescar 的愿景是让分布式事务的使用像本地事务的使用一样,简单和高效,并逐步解决开发者们遇到的分布式事务方面的所有难题。
Fescar 开源后,蚂蚁金服加入 Fescar 社区参与共建,并在 Fescar 0.4.0 版本中贡献了 TCC 模式。
为了打造更中立、更开放、生态更加丰富的分布式事务开源社区,经过社区核心成员的投票,大家决定对 Fescar 进行品牌升级,并更名为 Seata,意为:Simple Extensible Autonomous Transaction Architecture,是一套一站式分布式事务解决方案。
Seata 融合了阿里巴巴和蚂蚁金服在分布式事务技术上的积累,并沉淀了新零售、云计算和新金融等场景下丰富的实践经验,但要实现适用于所有的分布式事务场景的愿景,仍有很长的路要走。因此,我们决定建立一个完全中立的分布式事务组织,希望更多的企业、开发者能够加入我们,一起打造 Seata。
传统单体应用和现在分布式应用:
- 一个传统的单体应用,无论多少内部调用,最后终归是在同一个数据库上进行操作来完成一向业务操作,如图:
2. 随着业务量的发展,业务需求和架构发生了巨大的变化,整体架构由原来的单体应用逐渐拆分成为了微服务,原来的3个服务被从一个单体架构上拆开了,成为了3个独立的服务,分别使用独立的数据源,也不在之前共享同一个数据源了,具体的业务将由三个服务的调用来完成,如图:
本节中我们在SpringCloud环境下通过使用Seata来模拟用户购买商品的下单场景,创建3个子工程,分别是 :
order-server (下单服务)
storage-server(库存服务
account-server (支付服务)
技术选型及版本信息
注册中心:eureka
服务间调用:feign
持久层:mybatis
数据库:mysql 5.7.20
Springboot:2.1.7.RELEASE
Springcloud:Greenwich.SR2
jdk:1.8
seata:0.8
二. 准备环境
对seata还不了解的去
seata 官方文档地址 :http://seata.io/zh-cn/ 看看
seata1.0版本下载地址:https://github.com/seata/seata/releases
修改下载好的seata目录下的file.conf和registry.conf配置文件:
修改FILE.CONF配置文件
service {
#vgroup->rgroup
vgroup_mapping.my_test_tx_group = "default" ##修改这里将【vgroup_mapping.my_test_tx_group】修改为【vgroup_mapping.fsp_tx_group】
#only support single node
default.grouplist = "127.0.0.1:8091"
#degrade current not support
enableDegrade = false
#disable
disable = false
#unit ms,s,m,h,d represents milliseconds, seconds, minutes, hours, days, default permanent
max.commit.retry.timeout = "-1"
max.rollback.retry.timeout = "-1"
}
接着修改以下部分:
store {
## store mode: file、db
mode = "db" ##修改这里,表明事务信息用db存储
## file store 当mode=db时,此部分配置就不生效了,这是mode=file的配置
file {
dir = "sessionStore"
# branch session size , if exceeded first try compress lockkey, still exceeded throws exceptions
max-branch-session-size = 16384
# globe session size , if exceeded throws exceptions
max-global-session-size = 512
# file buffer size , if exceeded allocate new buffer
file-write-buffer-cache-size = 16384
# when recover batch read size
session.reload.read_size = 100
# async, sync
flush-disk-mode = async
}
## database store mode=db时,事务日志存储会存储在这个配置的数据库里
db {
## the implement of javax.sql.DataSource, such as DruidDataSource(druid)/BasicDataSource(dbcp) etc.
datasource = "dbcp"
## mysql/oracle/h2/oceanbase etc.
db-type = "mysql"
driver-class-name = "com.mysql.jdbc.Driver"
url = "jdbc:mysql://你的数据库的地址/seat" ##修改这里
user = "root" ##修改这里
password = "root" ##修改这里
min-conn = 1
max-conn = 3
global.table = "global_table"
branch.table = "branch_table"
lock-table = "lock_table"
query-limit = 100
}
}
修改REGISTRY.CONF配置文件
registry {
# file 、nacos 、eureka、redis、zk、consul、etcd3、sofa
type = "eureka" ## 修改这里将注册中心设置为eureka
## 若注册中心有修改则直接修改此处的配置
eureka {
serviceUrl = "http://localhost:8761/eureka"
application = "default"
weight = "1"
}
}
三. 配置数据库
先依次创建seata、seat-order、seat-account、seat-storage这四个数据库:
每个数据库里都要有回滚日志的日志记录表
然后呢,建项目,创建Eureka Server注册中心
然后依次建另外三个模块,配置基本一致,仅需要改改里面的一些名字,由于篇幅有限去看我另一篇文章,对这个配置在另一篇文章里,https://editor.csdn.net/md/?articleId=108363242
正常情况:
直接打开我们的浏览器然后输入以下的地址:http://localhost:8180/order/create?userId=1&productId=1&count=10&money=100,这时候我们可以看我们的启动的服务的控制台,大家会发现我们已经正常完成了整个事务的闭环。
验证异常事务回滚流程:
我在这里做了用户模块的用户不存在或者用户余额不足 ;
商品库存不足或者商品不存在;
以及突发某种不正常操作情况(用户掉线...)
直接修改我们的order-account的service中的代码如下所示:
/**
* 扣减账户余额
* @param userId 用户id
* @param money 金额
*/
@Override
public void decrease(Long userId, BigDecimal money) {
LOGGER.info("------->扣减账户开始account中");
accountDao.decrease(userId,money);
LOGGER.info("------->扣减账户结束account中");
//修改订单状态,此调用会导致调用成环
LOGGER.info("修改订单状态开始");
String mes = orderApi.update(userId, money.multiply(new BigDecimal("0.09")),0);
LOGGER.info("修改订单状态结束:{}",mes);
// 模拟异常错误
throw new RuntimeException("账户操作异常!");
}
然后重启我们的工程,然后再次访问我们刚刚的地址,这时候大家就会看到控制台报错,且我们在数据库会看到我们的数据都被回滚了。