環(huán)境搭建
Nacos搭建
最新版本快速搭建 使用Mysql模式
Nacos直接啟動即可。控制臺默認賬號密碼是nacos/nacos
,Mysql賬戶密碼有兩個 root/root
和 nacos/nacos
。
Seata搭建
Seata版本1.5.0 快速搭建
Seata1.5.0版本直接是一個SpringBoot項目,下載后修改application.yml 文件中注冊中心、配置中心、存儲模式配置。參考resources/application.example.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:file
registry:
#support:nacos,eureka,redis,zk,consul,etcd3,sofa
type:nacos
nacos:
application:seata-server
server-addr:127.0.0.1:8848
namespace:
group:SEATA_GROUP
cluster:default
username:nacos
password:nacos
##ifuseMSENacoswithauth,mutexwithusername/passwordattribute
#access-key:""
#secret-key:""
store:
#support:file、db、redis
mode:db
db:
datasource:druid
db-type:mysql
driver-class-name:com.mysql.jdbc.Driver
url:jdbc//127.0.0.1:3306/seata?rewriteBatchedStatements=true
user:root
password:root
min-conn:5
max-conn:100
global-table:global_table
branch-table:branch_table
lock-table:lock_table
distributed-lock-table:distributed_lock
query-limit:100
max-wait:5000
>基于SpringBoot+MyBatisPlus+Vue&Element實現的后臺管理系統(tǒng)+用戶小程序,支持RBAC動態(tài)權限、多租戶、數據權限、工作流、三方登錄、支付、短信、商城等功能
>
>*項目地址:
>*視頻教程:
#server:
>基于SpringCloudAlibaba+Gateway+Nacos+RocketMQ+Vue&Element實現的后臺管理系統(tǒng)+用戶小程序,支持RBAC動態(tài)權限、多租戶、數據權限、工作流、三方登錄、支付、短信、商城等功能
>
>*項目地址:
>*視頻教程:
#service-port:8091#Ifnotconfigured,thedefaultis'${server.port}+1000'
security:
secretKey:SeataSecretKey0c382ef121d778043159209298fd40bf3850a017
tokenValidityInMilliseconds:1800000
ignore:
urls:/,/**/*.css,/**/*.js,/**/*.html,/**/*.map,/**/*.svg,/**/*.png,/**/*.ico,/console-fe/public/**,/api/v1/auth/login
創(chuàng)建seata數據庫,執(zhí)行腳本建表
----------------------------------ThescriptusedwhenstoreModeis'db'--------------------------------
--thetabletostoreGlobalSessiondata
CREATETABLEIFNOTEXISTS`global_table`
(
`xid`VARCHAR(128)NOTNULL,
`transaction_id`BIGINT,
`status`TINYINTNOTNULL,
`application_id`VARCHAR(32),
`transaction_service_group`VARCHAR(32),
`transaction_name`VARCHAR(128),
`timeout`INT,
`begin_time`BIGINT,
`application_data`VARCHAR(2000),
`gmt_create`DATETIME,
`gmt_modified`DATETIME,
PRIMARYKEY(`xid`),
KEY`idx_status_gmt_modified`(`status`,`gmt_modified`),
KEY`idx_transaction_id`(`transaction_id`)
)ENGINE=InnoDB
DEFAULTCHARSET=utf8mb4;
--thetabletostoreBranchSessiondata
CREATETABLEIFNOTEXISTS`branch_table`
(
`branch_id`BIGINTNOTNULL,
`xid`VARCHAR(128)NOTNULL,
`transaction_id`BIGINT,
`resource_group_id`VARCHAR(32),
`resource_id`VARCHAR(256),
`branch_type`VARCHAR(8),
`status`TINYINT,
`client_id`VARCHAR(64),
`application_data`VARCHAR(2000),
`gmt_create`DATETIME(6),
`gmt_modified`DATETIME(6),
PRIMARYKEY(`branch_id`),
KEY`idx_xid`(`xid`)
)ENGINE=InnoDB
DEFAULTCHARSET=utf8mb4;
--thetabletostorelockdata
CREATETABLEIFNOTEXISTS`lock_table`
(
`row_key`VARCHAR(128)NOTNULL,
`xid`VARCHAR(128),
`transaction_id`BIGINT,
`branch_id`BIGINTNOTNULL,
`resource_id`VARCHAR(256),
`table_name`VARCHAR(32),
`pk`VARCHAR(36),
`status`TINYINTNOTNULLDEFAULT'0'COMMENT'0:locked,1:rollbacking',
`gmt_create`DATETIME,
`gmt_modified`DATETIME,
PRIMARYKEY(`row_key`),
KEY`idx_status`(`status`),
KEY`idx_branch_id`(`branch_id`),
KEY`idx_xid`(`xid`)
)ENGINE=InnoDB
DEFAULTCHARSET=utf8mb4;
CREATETABLEIFNOTEXISTS`distributed_lock`
(
`lock_key`CHAR(20)NOTNULL,
`lock_value`VARCHAR(20)NOTNULL,
`expire`BIGINT,
primarykey(`lock_key`)
)ENGINE=InnoDB
DEFAULTCHARSET=utf8mb4;
INSERTINTO`distributed_lock`(lock_key,lock_value,expire)VALUES('AsyncCommitting','',0);
INSERTINTO`distributed_lock`(lock_key,lock_value,expire)VALUES('RetryCommitting','',0);
INSERTINTO`distributed_lock`(lock_key,lock_value,expire)VALUES('RetryRollbacking','',0);
INSERTINTO`distributed_lock`(lock_key,lock_value,expire)VALUES('TxTimeoutCheck','',0);
啟動seata-server
,控制臺登錄頁面如下,賬號密碼為seata/seata
。
項目搭建
業(yè)務背景
用戶購買商品的業(yè)務邏輯。整個業(yè)務邏輯由3個微服務提供支持:
- 倉儲服務: 對給定的商品扣除倉儲數量。
- 訂單服務: 根據采購需求創(chuàng)建訂單。
- 帳戶服務: 從用戶帳戶中扣除余額。
架構
業(yè)務表創(chuàng)建
------------------------------
--Tablestructurefort_account
------------------------------
DROPTABLEIFEXISTS`t_account`;
CREATETABLE`t_account`
(
`id`int(11)NOTNULLAUTO_INCREMENT,
`user_id`varchar(255)DEFAULTNULL,
`amount`double(14,2
)DEFAULT'0.00',
PRIMARYKEY(`id`)
)ENGINE=InnoDBAUTO_INCREMENT=2DEFAULTCHARSET=utf8;
------------------------------
--Recordsoft_account
------------------------------
INSERTINTO`t_account`
VALUES('1','1','4000.00');
------------------------------
--Tablestructurefort_order
------------------------------
DROPTABLEIFEXISTS`t_order`;
CREATETABLE`t_order`
(
`id`int(11)NOTNULLAUTO_INCREMENT,
`order_no`varchar(255)DEFAULTNULL,
`user_id`varchar(255)DEFAULTNULL,
`commodity_code`varchar(255)DEFAULTNULL,
`count`int(11)DEFAULT'0',
`amount`double(14,2
)DEFAULT'0.00',
PRIMARYKEY(`id`)
)ENGINE=InnoDBAUTO_INCREMENT=64DEFAULTCHARSET=utf8;
------------------------------
--Recordsoft_order
------------------------------
------------------------------
--Tablestructurefort_stock
------------------------------
DROPTABLEIFEXISTS`t_stock`;
CREATETABLE`t_stock`
(
`id`int(11)NOTNULLAUTO_INCREMENT,
`commodity_code`varchar(255)DEFAULTNULL,
`name`varchar(255)DEFAULTNULL,
`count`int(11)DEFAULT'0',
PRIMARYKEY(`id`),
UNIQUEKEY`commodity_code`(`commodity_code`)
)ENGINE=InnoDBAUTO_INCREMENT=2DEFAULTCHARSET=utf8;
------------------------------
--Recordsoft_stock
------------------------------
INSERTINTO`t_stock`
VALUES('1','C201901140001','水杯','1000');
------------------------------
--Tablestructureforundo_log
--注意此處0.3.0+增加唯一索引ux_undo_log
------------------------------
DROPTABLEIFEXISTS`undo_log`;
CREATETABLE`undo_log`
(
`id`bigint(20)NOTNULLAUTO_INCREMENT,
`branch_id`bigint(20)NOTNULL,
`xid`varchar(100)NOTNULL,
`context`varchar(128)NOTNULL,
`rollback_info`longblobNOTNULL,
`log_status`int(11)NOTNULL,
`log_created`datetimeNOTNULL,
`log_modified`datetimeNOTNULL,
PRIMARYKEY(`id`),
UNIQUEKEY`ux_undo_log`(`xid`,`branch_id`)
)ENGINE=InnoDBAUTO_INCREMENT=1DEFAULTCHARSET=utf8;
------------------------------
--Recordsofundo_log
------------------------------
SET
FOREIGN_KEY_CHECKS=1;
服務創(chuàng)建
業(yè)務服務
以order服務為例,引入依賴、配置參數、提供創(chuàng)建訂單接口。
pom.xml文件中引入依賴
<dependencies>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-webartifactId>
dependency>
<dependency>
<groupId>com.alibaba.cloudgroupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discoveryartifactId>
dependency>
<dependency>
<groupId>com.alibaba.cloudgroupId>
<artifactId>spring-cloud-starter-alibaba-seataartifactId>
dependency>
<dependency>
<groupId>com.alibabagroupId>
<artifactId>druidartifactId>
dependency>
<dependency>
<groupId>com.baomidougroupId>
<artifactId>mybatis-plus-boot-starterartifactId>
dependency>
<dependency>
<groupId>mysqlgroupId>
<artifactId>mysql-connector-javaartifactId>
dependency>
dependencies>
application.properties配置參數
server.port=81
spring.application.name=order
spring.cloud.nacos.discovery.server-addr=127.0.0.1:8848
spring.cloud.nacos.username=nacos
spring.cloud.nacos.password=nacos
spring.datasource.type=com.alibaba.druid.pool.DruidDataSource
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc//127.0.0.1:3306/seata_samples?allowPublicKeyRetrieval=true&useSSL=false&useUnicode=true&characterEncoding=utf-8&allowMultiQueries=true
spring.datasource.username=root
spring.datasource.password=root
mybatis-plus.mapper-locations=classpath:mapper/*.xml
mybatis-plus.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl
提供創(chuàng)建訂單接口
@RequestMapping("/add")
publicvoidadd(StringuserId,StringcommodityCode,Integercount,BigDecimalamount){
Orderorder=newOrder();
order.setOrderNo(UUID.randomUUID().toString());
order.setUserId(userId);
order.setAmount(amount);
order.setCommodityCode(commodityCode);
order.setCount(count);
orderService.save(order);
}
聚合服務
business服務遠程調用倉儲、訂單、帳戶服務,完成下單流程。
1.pom.xml文件中引入依賴
<dependencies>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-webartifactId>
dependency>
<dependency>
<groupId>com.alibaba.cloudgroupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discoveryartifactId>
dependency>
<dependency>
<groupId>com.alibaba.cloudgroupId>
<artifactId>spring-cloud-starter-alibaba-seataartifactId>
dependency>
<dependency>
<groupId>com.alibabagroupId>
<artifactId>druidartifactId>
dependency>
<dependency>
<groupId>org.springframework.cloudgroupId>
<artifactId>spring-cloud-starter-openfeignartifactId>
dependency>
dependencies>
2.application.properties配置參數
server.port=80
spring.application.name=business
spring.cloud.nacos.discovery.server-addr=127.0.0.1:8848
spring.cloud.nacos.username=nacos
spring.cloud.nacos.password=nacos
spring.datasource.type=com.alibaba.druid.pool.DruidDataSource
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc//127.0.0.1:3306/seata_samples?allowPublicKeyRetrieval=true&useSSL=false&useUnicode=true&characterEncoding=utf-8&allowMultiQueries=true
spring.datasource.username=root
spring.datasource.password=root
service.disableGlobalTransaction=false
# 連接超時時間
ribbon.ConnectTimeout=3000
# 響應超時時間
ribbon.ReadTimeout=5000
3.聲明account、stock、order的feign接口。
@FeignClient(value="account")
publicinterfaceAccountFeign{
@RequestMapping("/account/reduce")
publicvoidreduce(@RequestParam("userId")StringuserId,@RequestParam("amount")BigDecimalamount);
}
@FeignClient(value="order")
publicinterfaceOrderFeign{
@RequestMapping("/order/add")
publicvoidadd(@RequestParam("userId")StringuserId,@RequestParam("commodityCode")StringcommodityCode,@RequestParam("count")Integercount,@RequestParam("amount")BigDecimalamount);
}
@FeignClient(value="stock")
publicinterfaceStockFeign{
@RequestMapping("/stock/deduct")
publicvoiddeduct(@RequestParam("commodityCode")StringcommodityCode,@RequestParam("count")Integercount);
}
4.全局事務開啟,調用feign接口
@Autowired
privateOrderFeignorderFeign;
@Autowired
privateStockFeignstockFeign;
@Autowired
privateAccountFeignaccountFeign;
@GlobalTransactional
@RequestMapping("/toOrder")
publicvoidtoOrder(StringuserId,StringcommodityCode,Integercount,BigDecimalamount){
accountFeign.reduce(userId,amount);
stockFeign.deduct(commodityCode,count);
orderFeign.add(userId,commodityCode,count,amount);
}
測試驗證
當前資金賬戶4000,庫存1000,模擬用戶購買商品2000個,消費4000,業(yè)務調用后,數據庫數據狀態(tài)應該如下:
- 用戶資金滿足4000,數據庫更新用戶資金為0。
- 商品庫存不滿足2000個,異常。
- business服務提交全局回滾。
- 資金服務回滾操作,更新資金為4000。
驗證:
1.瀏覽器輸入地址請求訪問
- http://127.0.0.1/business/toOrder?userId=1&commodityCode=C201901140001&count=2000&amount=4000
2.account、stock服務日志觀察。
3.數據庫數據依然為原始狀態(tài)。
注意事項
1.Seata1.5版本的mysql驅動是5.7,需要為8,在libs文件夾刪除mysql-connector-java-5.xx.jar
,替換mysql-connector-java-8.xx.jar
即可
2.Spring Boot &Spring Cloud&Spring Cloud Alibaba
版本兼容問題
Spring Cloud Alibaba版本說明
3.druid和數據驅動版本兼容
通過druid倉庫版本查看各依賴版本說明
代碼倉庫
- https://gitee.com/codeWBG/springcloud_alibaba
-
代碼
+關注
關注
30文章
4779瀏覽量
68525 -
管理系統(tǒng)
+關注
關注
1文章
2485瀏覽量
35903 -
spring
+關注
關注
0文章
340瀏覽量
14338
原文標題:保姆級教程:Spring Cloud 集成 Seata 分布式事務
文章出處:【微信號:芋道源碼,微信公眾號:芋道源碼】歡迎添加關注!文章轉載請注明出處。
發(fā)布評論請先 登錄
相關推薦
評論