分布式事务——dubbo集成seata示例
1. 背景
在分布式事务框架选型中,seata
一定会出现在评估范围内,这里通过dubbo项目集成seata tcc事务模式来体验seata的分布式事务。
seata
版本1.5.2
2. 源码启动seata-server
1. 初始化配置到nacos
初始化seata
的配置脚本在源码目录/seata/script/config-center/nacos
,执行以下命令初始化配置到nacos,nacos要先开启
sh nacos-config.sh -h localhost -p 8848 -g SEATA_GROUP -t default -u nacos -w nacos
有些属性添加报错,不用理会,不影响
按属性保存在nacos中的,而不是按文件,原因暂时不清楚。
这里日志存储在mysql中,所以要改对应的属性
store.mode=db
store.db.url=
store.db.user=
store.db.password=
mysql初始化脚本在seata/script/server/db/mysql.sql
.
2. 修改server中的application.yml
seata/server
中application.yml
server:
port: 7091
spring:
application:
name: seata-server
logging:
config: classpath:logback-spring.xml
file:
path: ${user.home}/logs/seata
extend:
logstash-appender:
destination: 127.0.0.1:4560
kafka-appender:
bootstrap-servers: 127.0.0.1:9092
topic: logback_to_logstash
# 管理界面账号密码
console:
user:
username: seata
password: seata
seata:
config:
# support: nacos, consul, apollo, zk, etcd3
type: nacos
nacos:
server-addr: 127.0.0.1:8848
namespace: 405e877e-56ab-4755-8dd8-6541e1ee4845
group: SEATA_GROUP
username: nacos
password: nacos
#data-id: seataServer.properties
# 注册seata-server
registry:
# support: nacos, eureka, redis, zk, consul, etcd3, sofa
type: nacos
preferred-networks: 30.240.*
nacos:
application: seata-server
server-addr: 127.0.0.1:8848
group: SEATA_GROUP
namespace: 405e877e-56ab-4755-8dd8-6541e1ee4845
cluster: default
username: nacos
password: nacos
security:
secretKey: SeataSecretKey0c382ef121d778043159209298fd40bf3850a017
tokenValidityInMilliseconds: 1800000
ignore:
urls: /,/**/*.css,/**/*.js,/**/*.html,/**/*.map,/**/*.svg,/**/*.png,/**/*.ico,/console-fe/public/**,/api/v1/auth/login
3. 启动server
运行ServerApplication
如果遇到启动报如下错误:
A component required a bean of type 'io.seata.server.console.service.BranchSessionService' that could not be found.
是因为nacos配置中store.mode值DB大小问题,应该改成小写
3. TCC模式示例
技术组件:springboot、dubbo、zookeeper、nacos、seata
主体流程:创建订单,分别调用账户服务减余额,调用库存服务减库存
项目结构:
目标:创建订单成功后,调用账户服务和库存服务commit(),过程中有异常则调用服务rollback().
1. 接口定义
/**
* 数字藏品账户服务
* @author Tarzan写bug
* @date 2022/12/08
*/
@LocalTCC
public interface DigitalAccountService {
/**
* 扣钱
* @param id
* @param money
* @return
*/
@TwoPhaseBusinessAction(name = "digitalAccountService", commitMethod = "commitDeductMoney", rollbackMethod = "rollbackDeductMoney")
AccountDTO deductMoney(BusinessActionContext businessActionContext, Long id, BigDecimal money);
AccountDTO commitDeductMoney(BusinessActionContext businessActionContext);
AccountDTO rollbackDeductMoney(BusinessActionContext businessActionContext);
}
/**
* 数字藏品库存
* @author Tarzan写bug
* @date 2022/12/08
*/
@LocalTCC
public interface DigitalInstockService {
/**
* 减库存
* @param instockNum
*/
@TwoPhaseBusinessAction(name = "digitalInstockService", commitMethod = "commitDeductInstock", rollbackMethod = "rollbackDeductInstock")
void deductInstock(long instockNum);
void commitDeductInstock(BusinessActionContext businessActionContext);
void rollbackDeductInstock(BusinessActionContext businessActionContext);
}
/**
* 数字藏品订单
* @author Tarzan写bug
* @date 2022/12/08
*/
public interface DigitalOrderService {
/**
* 创建订单
* @param id
*/
void createOrder(Long id);
}
在定义分支事务的时候,在接口类上标注@LocalTCC
,定义3个方法prepare()
、commit()
、rollback()
,在prepare()
上标注@TwoPhaseBusinessAction
,注解中的属性值name
为bean的名称,commitMethod
为提交方法的名称,rollbackMethod
为回滚方法的名称。
2. 提供者端
添加seata的maven
依赖
<dependency>
<groupId>io.seata</groupId>
<artifactId>seata-spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba.nacos</groupId>
<artifactId>nacos-client</artifactId>
</dependency>
application.yml
中添加seata client配置
seata:
enabled: true
# 应用名称
application-id: digital-instock-provider
# 事务组,要和服务端配置保持一致
tx-service-group: default_tx_group
client:
rm-report-success-enable: true
rm-table-meta-check-enable: false
rm-report-retry-count: 5
rm-async-commit-buffer-limit: 10000
rm:
lock:
retry-interval: 10
retry-times: 30
retry-policy-branch-rollback-on-conflict: true
tm:
commit-retry-count: 3
rollback-retry-count: 3
undo:
data-validation: true
log-serialization: jackson
log-table: undo_log
service:
# 跟服务端配置保持一致
vgroup-mapping:
default_tx_group: default
enable-degrade: false
disable-global-transaction: false
grouplist:
default: 127.0.0.1:8091
transport:
shutdown:
wait: 3
thread-factory:
boss-thread-prefix: NettyBoss
worker-thread-prefix: NettyServerNIOWorker
server-executor-thread-prefix: NettyServerBizHandler
share-boss-worker: false
client-selector-thread-prefix: NettyClientSelector
client-selector-thread-size: 1
client-worker-thread-prefix: NettyClientWorkerThread
type: tcp
server: nio
heartbeat: true
serialization: seata
compressor: none
enable-client-batch-send-request: true
registry:
type: nacos
nacos:
server-addr: localhost:8848
namespace: 405e877e-56ab-4755-8dd8-6541e1ee4845
group: SEATA_GROUP
username: nacos
password: nacos
config:
type: nacos
nacos:
server-addr: localhost:8848
namespace: 405e877e-56ab-4755-8dd8-6541e1ee4845
group: SEATA_GROUP
username: nacos
password: nacos
# 貌似没什么用
data-id: SEATA_CLIENT.properties
配置中主要关注seata.tx-service-group
和seata.service.vgroup-mapping
属性要跟服务端配置的保持一致,不然会报如下错误:
can not get cluster name in registry config 'service.vgroupMapping.oauth-seata-service-group', please make sure registry config correct
在事务发起者方法上添加@GlobalTransactional
注解
@GlobalTransactional
@Override
public void createOrder(Long id) {
LOGGER.info(this.getClass() + " createOrder()");
accountService.deductMoney(null, id, new BigDecimal(100));
instockService.deductInstock(2L);
}
3. 消费者端
dubbo消费者端不涉及seata.
4. 总结
代码收录在https://gitee.com/ouwenrts/seata-demo.git
世界那么大,感谢遇见,未来可期…
欢迎同频共振的那一部分人
作者公众号:Tarzan写bug
淘宝店:Tarzan小店
提供一元解决Java问题和其他方面的解决方案,欢迎咨询