项目场景:
我发现:公司项目中有个业务逻辑会有用到feign调用去修改员工数据,然而可能遇到超时的情况,从而导致脏数据的出现。基于公司采用的是eureka集群,所以就萌生了想要搭建《eureka集群+seata集群》的想法
环境准备:
在官网请务必核对版本对应关系
我的配置版本如下:
spring-boot :2.1.6.RELEASE
spring-cloud :Greenwich.SR2
spring-cloud-alibaba : 2.1.2.RELEASE
seata :1.3.0
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-seata</artifactId>
<version>2.1.2.RELEASE</version>
<exclusions>
<exclusion>
<groupId>io.seata</groupId>
<artifactId>seata-spring-boot-starter</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>io.seata</groupId>
<artifactId>seata-spring-boot-starter</artifactId>
<version>1.3.0</version>
</dependency>
- eureka集群 + Seata集群:
逐步解析:
- 下载 Seata - 1.3.0版本
- 解压得到如下目录
.
├──bin
├──seata-server.bat
├──seata-server.sh
├──conf
├──file.conf (需修改配置)
├──file.conf.example (可参考实例)
├──registry.conf (需修改配置)
├──lib
└──log
- 修改<file.conf>配置信息(只展示我修改过的地方)
store {
## store mode: file、db、redis
mode = "db"
## database store property
db {
## the implement of javax.sql.DataSource, such as DruidDataSource(druid)/BasicDataSource(dbcp)/HikariDataSource(hikari) etc.
datasource = "dbcp"
## mysql/oracle/postgresql/h2/oceanbase etc.
dbType = "mysql"
## driverClassName = "com.mysql.jdbc.Driver"
driverClassName = "com.mysql.cj.jdbc.Driver"
url = "jdbc:mysql://127.0.0.1:3306/seata?useAffectedRows=true&serverTimezone=UTC&characterEncoding=utf-8"
user = "root"
password = "root"
minConn = 5
maxConn = 100
globalTable = "global_table"
branchTable = "branch_table"
lockTable = "lock_table"
queryLimit = 100
maxWait = 5000
}
}
mode = "db"模式下时,参考官方新建这几个表:global_table,branch_table,lock_table
(undo_log 其实不用加,当时复制粘贴比较快)
- 修改<registry.conf>配置信息(只展示我修改过的地方,其他的默认)
registry {
# file 、nacos 、eureka、redis、zk、consul、etcd3、sofa
type = "eureka"
loadBalance = "RandomLoadBalance"
loadBalanceVirtualNodes = 10
eureka {
# serviceUrl = "http://127.0.0.1:8889/eureka"
serviceUrl = "http://eureka7001.com:7001/eureka/,http://eureka7002.com:7002/eureka/,http://eureka7003.com:7003/eureka/"
application = "seata-server"
weight = "1"
}
}
-
启动Eureka集群,并启动Seata集群(注:另一台Seata配置也一样,不是同一台机器的话就需要稍修改连接 db:url)
-
yml文件来配置每个业务模块的Seata信息(不同之处我都注释起来了,请悉知)
spring:
application:
# name: account-server
# name: order-server
name: storage-server
server:
# port: 8180
# port: 8182
port: 8183
eureka:
instance:
hostname: localhost
prefer-ip-address: true
client:
serviceUrl:
defaultZone: http://eureka7001.com:7001/eureka/,http://eureka7002.com:7002/eureka/,http://eureka7003.com:7003/eureka/
seata:
enabled: true
application-id: ${spring.application.name}
tx-service-group: my_test_tx_group_yjy
service:
vgroup-mapping:
my_test_tx_group_yjy: seata-server # 找到seata集群中名为"seata-server"的application
registry:
type: eureka # 注册中心为eureka
eureka:
application: ${spring.application.name}
service-url: http://eureka7001.com:7001/eureka/,http://eureka7002.com:7002/eureka/,http://eureka7003.com:7003/eureka/
-
注意修改 C:\Windows\System32\drivers\etc\hosts 文件
-
每个业务模块对应的数据库也需要加上 undo_log 表
-
启动类加上 @EnableAutoDataSourceProxy 注解用来自动开启数据源代理,可参考官方文档
-
在业务层加上 @GlobalTransactional (注:该全局事务注解范围必须 >= @Transactional本地事务注解)
-
运行测试效果
-
项目源码>>(https://gitee.com/oksir/springcloud-eureka-feign-mybatis-seata-master)
总结:
其实我在项目运行中,也遇到了一些小问题,由于时间比较紧,就来不及记录了。
可以看到,SeaTa - AT的本质都是基于undo_log的交易补偿,当然这也是AT模式的特点吧,这些复杂性其实也并不是seata本身造成的,而是微服务的拆分带来的系统架构的复杂性。