这几天在使用微服务进行开发,搭建架构时需要集成Seata分布式事务管理,中间遇到了一些坑,决定写这篇文章以后集成Seata时可以快速解决问题
1.Seata简介
1.1Seata是什么
Seata 是一款开源的分布式事务解决方案,致力于在微服务架构下提供高性能和简单易用的分布式事务服务。在 Seata 开源之前,Seata 对应的内部版本在阿里经济体内部一直扮演着分布式一致性中间件的角色,帮助经济体平稳的度过历年的双11,对各BU业务进行了有力的支撑。经过多年沉淀与积累,商业化产品先后在阿里云、金融云进行售卖。2019.1 为了打造更加完善的技术生态和普惠技术成果,Seata 正式宣布对外开源,未来 Seata 将以社区共建的形式帮助其技术更加可靠与完备。
1.2AT模式
- 提供无侵入自动补偿的事务模式,目前已支持 MySQL、 Oracle 、PostgreSQL和 TiDB的AT模式,H2 开发中
1.3TCC模式
- 支持 TCC 模式并可与 AT 混用,灵活度更高
1.4SAGA模式
- 为长事务提供有效的解决方案
1.5XA模式
- 似乎正在研发中
- 总而言之,大部分情况下我们需要了解的是AT模式
2.Seata的下载与运行
2.1下载
- 直接官网下载:https://seata.io/zh-cn/index.html
- windows下载zip包,linux下载tar.gz即可,我使用的是1.4.0版本的
2.2运行
- 将下载好的压缩包解压
- 解压后直接执行bin下面的seata-server.sh(windows双击seata-server.bat)即可运行seata,默认端口是8091
3.Nacos集成
3.1添加Seata配置到Nacos中
- 基本配置配置如下,具体配置请查阅官方文档
#这里的demo-system-group表示当前的组,用户可以自己定义组名如lat-system-group也可,但是在后面配置文件中必须对应,见5.注意点详解
service.vgroupMapping.demo-system-group=default
store.mode=db
store.db.datasource=druid
store.db.dbType=mysql
store.db.driverClassName=com.mysql.jdbc.Driver
store.db.url=jdbc:mysql://127.0.0.1:3306/ry-seata?useUnicode=true
store.db.user=root
store.db.password=password
store.db.minConn=5
store.db.maxConn=30
store.db.globalTable=global_table
store.db.branchTable=branch_table
store.db.queryLimit=100
store.db.lockTable=lock_table
store.db.maxWait=5000
#下面这条配置修改了写日志时序列化数据的方式,如果不修改序列化方式可能出现意外的错误,见5.注意点
client.undo.logSerialization=kryo
- 注意这里的配置每行都对应一个Data Id,配置完成后Nacos配置文件应如下图(部分配置)
3.2将Seata注册到Nacos中
- 打开解压后的压缩包在config文件夹下,编辑修改registry.conf文件,本人如下(注册中心和配置中心都选择nacos)
registry {
# file 注册信息在指定文件下
# nacos 注册到nacos注册中心
# eureka注册到eureka注册中心
# redis 注册到redis作为注册中心
# zk 注册到zk注册中心
# consul注册到consul注册中心
# etcd3 注册到etcd3注册中心
# sofa 注册到sofa注册中心
type = "nacos"
loadBalance = "RandomLoadBalance"
loadBalanceVirtualNodes = 10
nacos {
application = "seata-server"
serverAddr = "192.168.100.201:8849"
group = "SEATA_GROUP"
namespace = ""
cluster = "default"
username = "nacos"
password = "nacos"
}
eureka {
serviceUrl = "http://localhost:8761/eureka"
application = "default"
weight = "1"
}
redis {
serverAddr = "localhost:6379"
db = 0
password = ""
cluster = "default"
timeout = 0
}
zk {
cluster = "default"
serverAddr = "127.0.0.1:2181"
sessionTimeout = 6000
connectTimeout = 2000
username = ""
password = ""
}
consul {
cluster = "default"
serverAddr = "127.0.0.1:8500"
}
etcd3 {
cluster = "default"
serverAddr = "http://localhost:2379"
}
sofa {
serverAddr = "127.0.0.1:9603"
application = "default"
region = "DEFAULT_ZONE"
datacenter = "DefaultDataCenter"
cluster = "default"
group = "SEATA_GROUP"
addressWaitTime = "3000"
}
file {
name = "file.conf"
}
}
config {
# 同上,选择一个配置中心
type = "nacos"
nacos {
serverAddr = "192.168.100.201:8849"
namespace = ""
group = "SEATA_GROUP"
username = "nacos"
password = "nacos"
}
consul {
serverAddr = "127.0.0.1:8500"
}
apollo {
appId = "seata-server"
apolloMeta = "http://192.168.1.204:8801"
namespace = "application"
apolloAccesskeySecret = ""
}
zk {
serverAddr = "127.0.0.1:2181"
sessionTimeout = 6000
connectTimeout = 2000
username = ""
password = ""
}
etcd3 {
serverAddr = "http://localhost:2379"
}
file {
name = "file.conf"
}
}
3.3添加Seata数据库
- 微服务大多是分库的,这里给Seata一个独立的数据库方便Seata持久化,建表语句如下
-- -------------------------------- The script used when storeMode is 'db' --------------------------------
-- the table to store GlobalSession data
CREATE TABLE IF NOT EXISTS `global_table`
(
`xid` VARCHAR(128) NOT NULL,
`transaction_id` BIGINT,
`status` TINYINT NOT NULL,
`application_id` VARCHAR(32)