网站名称 域名,深圳网上招聘最好的网站,平邑网站开发,招工 最新招聘信息怎么写目录 准备调整db配置准备创建数据库 seata配置nacos配置confi.txt下载向nacos推送配置的脚本 启动seata新建项目order-seata项目 订单项目数据库脚本pom.xmlapplication.yml启动类实体类dao类service类controller类feign类mapper类 stock-seata 库存项目数据库脚本pom.xmlappli… 目录 准备调整db配置准备创建数据库 seata配置nacos配置confi.txt下载向nacos推送配置的脚本 启动seata新建项目order-seata项目 订单项目数据库脚本pom.xmlapplication.yml启动类实体类dao类service类controller类feign类mapper类 stock-seata 库存项目数据库脚本pom.xmlapplication.yml启动类实体类dao类service类controller类mapper类 测试特殊情况分布式事务order-seata项目变动pom.xmlapplication.ymlcontroller stock-seata项目变动pom.xmlapplication.yml 脚本效果 分布式事务原理nacos配置问题seata的几个表都是什么情况 准备
名称版本Nacos1.4.5seata1.4.0alibabacloud2.2.5.RELEASE
本博客版本
seata官网地址 seata安装包下载
没有linux服务器可本地搭建玩一下注意alibaba版本跟seata版本一定要严格控制不然会出现一些奇奇怪怪的问题 默认数据存储分为2钟一种是存在bin目录下的root.data文件里面还有一种是db方式本文使用db模式 调整db配置
注意mysql数据库的版本得5.7以上。- 修改配置文件之前别慌先copy一遍再说养成好习惯 调整模式为db, 修改db对应的配置
准备创建数据库 mysql脚本下载地址
先把整个项目下载然后到这个目录下找到mysql.sql
seata配置nacos 先备份一下配置文件 删除其他没有用的配置调整一下配置
配置confi.txt
到之前下载好的依赖包中copy对应的config.txt文件放到seata目录下
修改存储类型 调整为自己对应的url地址以及账号和密码
下载向nacos推送配置的脚本 将该脚本移动到seata的conf配置下
sh nacos-config.sh -h 127.0.0.1 -p 8848 -g SEATA_GROUP -t seata -u nacos -w nacos
# h: nacos服务ip.
# p: nacos服务端口号.
# g: 想要的分组信息.
# t: 第一步新建的命名空间.
# u: nacos登录名.
# w: nacos登录密码
如果是本地没有做任务的修改直接运行就行
大概运行5分钟左右 很奇葩的设计搞不懂为什么不单独弄一个文件来存储所有的内容而是key value的方式看起来很乱建议单独创建一个seata的命令空间用来存储这些配置
启动seata window启动用bat文件 可以看出默认端口为8091也可以自定义 在服务列表中就可以看到多了一个seata-server的服务因为window版本不好演示集群方式所以我这里的集群数量是1
新建项目 在之前的基础上新增一个seata项目 注意新增后该项目是没有蓝点的 添加号解决蓝点问题 自己手动补一下seata这个目录 创建模块order-seata和stock-seata
order-seata项目 订单项目 新增这两个项目 库存项目的结构
数据库脚本
create database seata_order;
use seata_order;CREATE TABLE order_tbl (id int(11) NOT NULL AUTO_INCREMENT,product_id varchar(200) DEFAULT NULL,total_amount decimal(10,3) DEFAULT NULL,statu int(11) DEFAULT NULL,PRIMARY KEY (id)
) ENGINEInnoDB AUTO_INCREMENT9 DEFAULT CHARSETutf8新增数据库
pom.xml
project xmlnshttp://maven.apache.org/POM/4.0.0 xmlns:xsihttp://www.w3.org/2001/XMLSchema-instancexsi:schemaLocationhttp://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsdmodelVersion4.0.0/modelVersionparentgroupIdcom.lcs.springcloud/groupIdartifactIdspringcloudalibaba/artifactIdversion0.0.1-SNAPSHOT/version/parentartifactIdorder-nacos/artifactIdpackagingjar/packagingdependenciesdependencygroupIdjunit/groupIdartifactIdjunit/artifactIdversion3.8.1/versionscopetest/scope/dependencydependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-web/artifactId/dependencydependencygroupIdcom.alibaba.cloud/groupIdartifactIdspring-cloud-starter-alibaba-nacos-discovery/artifactIdexclusionsexclusiongroupIdorg.springframework.cloud/groupIdartifactIdspring-cloud-starter-netflix-ribbon/artifactId/exclusion/exclusions/dependencydependencygroupIdcom.alibaba.cloud/groupIdartifactIdspring-cloud-starter-alibaba-sentinel/artifactId/dependencydependencygroupIdorg.springframework.cloud/groupIdartifactIdspring-cloud-starter-openfeign/artifactIdexclusionsexclusiongroupIdorg.springframework.cloud/groupIdartifactIdspring-cloud-netflix-ribbon/artifactId/exclusion/exclusions/dependencydependencygroupIdorg.springframework.cloud/groupIdartifactIdspring-cloud-starter-loadbalancer/artifactId/dependency/dependenciesbuildfinalNameorder/finalName/build
/project
application.yml
server:port: 8190spring:application:name: order-seatacloud:nacos:discovery:namespace: publicserver-addr: localhost:8848username: nacospassword: nacosdatasource:type: com.alibaba.druid.pool.DruidDataSourcedruid:db-type: mysqldriver-class-name: com.mysql.jdbc.Driverurl: jdbc:mysql://192.168.10.108:3306/seata_order?useUnicodetruecharacterEncodingutf-8allowMultiQueriestrueuseSSLfalseserverTimezoneAsia/ShanghaiallowPublicKeyRetrievaltrueuseCursorFetchtrueusername: rootpassword: 12312312
mybatis:mapper-locations: classpath:mapper/*.xml
启动类
package com.lcs.springcloud;import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.openfeign.EnableFeignClients;SpringBootApplication
MapperScan(com.lcs.springcloud.dao)
EnableFeignClients
public class OrderSeataApplication {public static void main(String[] args) {SpringApplication.run(OrderSeataApplication.class);}
}
实体类
package com.lcs.springcloud.entity;import java.math.BigDecimal;public class OrderTbl {private Integer id;private String product_id;private BigDecimal total_amount;private Integer statu;public OrderTbl() {}public Integer getId() {return id;}public void setId(Integer id) {this.id id;}public String getProduct_id() {return product_id;}public void setProduct_id(String product_id) {this.product_id product_id;}public BigDecimal getTotal_amount() {return total_amount;}public void setTotal_amount(BigDecimal total_amount) {this.total_amount total_amount;}public Integer getStatu() {return statu;}public void setStatu(Integer statu) {this.statu statu;}Overridepublic String toString() {return OrderTbl{ id id , product_id product_id \ , total_amount total_amount , statu statu };}
}
dao类
package com.lcs.springcloud.dao;import com.lcs.springcloud.entity.OrderTbl;
import org.springframework.stereotype.Repository;Repository
public interface OrderDao {void insert(OrderTbl orderTbl);
}service类
package com.lcs.springcloud.service;import com.lcs.springcloud.dao.OrderDao;
import com.lcs.springcloud.entity.OrderTbl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;Service
public class OrderService {AutowiredOrderDao orderDao;public void insert(OrderTbl orderTbl) {orderDao.insert(orderTbl);}
}
controller类
package com.lcs.springcloud.controller;import com.lcs.springcloud.entity.OrderTbl;
import com.lcs.springcloud.feign.StockOpenFeign;
import com.lcs.springcloud.service.OrderService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;import java.math.BigDecimal;RestController
RequestMapping(/order)
public class OrderController {AutowiredOrderService orderService;AutowiredStockOpenFeign stockOpenFeign;RequestMapping(/add)public String add(){OrderTbl orderTbl new OrderTbl();orderTbl.setProduct_id(10);orderTbl.setTotal_amount(new BigDecimal(3000));orderTbl.setStatu(0);orderService.insert(orderTbl);String reduct stockOpenFeign.reduct(orderTbl.getProduct_id());return add order reduct;}
}
feign类
package com.lcs.springcloud.controller;import com.lcs.springcloud.entity.OrderTbl;
import com.lcs.springcloud.feign.StockOpenFeign;
import com.lcs.springcloud.service.OrderService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;import java.math.BigDecimal;RestController
RequestMapping(/order)
public class OrderController {AutowiredOrderService orderService;AutowiredStockOpenFeign stockOpenFeign;RequestMapping(/add)public String add(){OrderTbl orderTbl new OrderTbl();orderTbl.setProduct_id(10);orderTbl.setTotal_amount(new BigDecimal(3000));orderTbl.setStatu(0);orderService.insert(orderTbl);String reduct stockOpenFeign.reduct(orderTbl.getProduct_id());return add order reduct;}
}
mapper类
?xml version1.0 encodingUTF-8?
!DOCTYPE mapper PUBLIC -//mybatis.org//DTD Mapper 3.0//EN http://mybatis.org/dtd/mybatis-3-mapper.dtd
mapper namespacecom.lcs.springcloud.dao.OrderDao!-- 主键自增长的插入 --insert idinsert parameterTypecom.lcs.springcloud.entity.OrderTbl useGeneratedKeystrue keyPropertyidinsert into order_tbl(product_id,total_amount,statu) values(#{product_id},#{total_amount},#{statu});/insert
/mapper
stock-seata 库存项目 数据库脚本 create database seata_stock;
use seata_stock;CREATE TABLE stock_tbl (id int(11) NOT NULL AUTO_INCREMENT,product_id varchar(200) DEFAULT NULL,count int(11) DEFAULT NULL,PRIMARY KEY (id)
) ENGINEInnoDB AUTO_INCREMENT2 DEFAULT CHARSETutf8INSERT INTO seata_stock.stock_tbl (id, product_id, count) VALUES (1, 10, 100);pom.xml
project xmlnshttp://maven.apache.org/POM/4.0.0 xmlns:xsihttp://www.w3.org/2001/XMLSchema-instancexsi:schemaLocationhttp://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsdmodelVersion4.0.0/modelVersionparentgroupIdcom.lcs.springcloud/groupIdartifactIdspringcloudalibaba/artifactIdversion0.0.1-SNAPSHOT/version/parentartifactIdstock-seata/artifactIdpackagingjar/packagingdependencies!-- Nacos服务注册发现--dependencygroupIdcom.alibaba.cloud/groupIdartifactIdspring-cloud-starter-alibaba-nacos-discovery/artifactId/dependency!--继承了父项目不需要添加版本号--dependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-web/artifactId/dependency!-- jdbc --dependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-jdbc/artifactIdversion2.3.5.RELEASE/version/dependency!-- mybatis --dependencygroupIdorg.mybatis.spring.boot/groupIdartifactIdmybatis-spring-boot-starter/artifactIdversion1.3.2/version!-- 排除冲突的jar包文件--exclusionsexclusiongroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-jdbc/artifactId/exclusion/exclusions/dependency!--Mysql驱动器--dependencygroupIdmysql/groupIdartifactIdmysql-connector-java/artifactIdversion8.0.18/versionscoperuntime/scope/dependency!-- druid--dependencygroupIdcom.alibaba/groupIdartifactIddruid-spring-boot-starter/artifactIdversion1.1.9/version/dependency/dependenciesbuildfinalNameorder-seata/finalName/build
/project
application.yml
server:port: 8200spring:application:name: stock-seatacloud:nacos:discovery:namespace: publicserver-addr: localhost:8848username: nacospassword: nacosdatasource:type: com.alibaba.druid.pool.DruidDataSourcedruid:db-type: mysqldriver-class-name: com.mysql.jdbc.Driver#url: jdbc:mysql://10.153.96.31:3306/iomm-collection?useUnicodetruecharacterEncodingutf-8allowMultiQueriestrueuseSSLfalseserverTimezoneAsia/ShanghaiallowPublicKeyRetrievaltrueuseCursorFetchtrueurl: jdbc:mysql://112.74.51.171:3306/seata_stock?useUnicodetruecharacterEncodingutf-8allowMultiQueriestrueuseSSLfalseserverTimezoneAsia/ShanghaiallowPublicKeyRetrievaltrueuseCursorFetchtrueusername: rootpassword: Zy_746498
mybatis:mapper-locations: classpath:mapper/*.xml
启动类
package com.lcs.springcloud;import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;SpringBootApplication
MapperScan(com.lcs.springcloud.dao)
public class StockSeataApplication {public static void main(String[] args) {SpringApplication.run(StockSeataApplication.class,args);}
}
实体类
package com.lcs.springcloud.entity;public class StockTbl {private Integer id;private String product_id;private Integer count;public Integer getId() {return id;}public void setId(Integer id) {this.id id;}public String getProduct_id() {return product_id;}public void setProduct_id(String product_id) {this.product_id product_id;}public Integer getCount() {return count;}public void setCount(Integer count) {this.count count;}
}
dao类
package com.lcs.springcloud.dao;import org.apache.ibatis.annotations.Param;
import org.springframework.stereotype.Repository;Repository
public interface StockDao {void updateStock(Param(product_id)String product_id);
}
service类
package com.lcs.springcloud.service;import com.lcs.springcloud.dao.StockDao;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;Service
public class StockService {AutowiredStockDao stockDao;public String updateStock(String product_id) {try {stockDao.updateStock(product_id);return 扣减库存成功;}catch (Exception e){return 更新库存失败;}}
}
controller类
package com.lcs.springcloud.controller;import com.lcs.springcloud.service.StockService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;RestController
RequestMapping(/stock)
public class StockController {AutowiredStockService stockService;Value(${server.port})String port;RequestMapping(/reduct)public String reduct(RequestParam(value product_id) String product_id){return stockService.updateStock(product_id);}}
mapper类
?xml version1.0 encodingUTF-8?
!DOCTYPE mapper PUBLIC -//mybatis.org//DTD Mapper 3.0//EN http://mybatis.org/dtd/mybatis-3-mapper.dtd
mapper namespacecom.lcs.springcloud.dao.StockDao!-- 主键自增长的插入 --update idupdateStock parameterTypejava.lang.String update stock_tbl SET count count-1 where product_id#{product_id}/update
/mapper
测试
前提 保持已经开启nacos不知道的可以先学习一下nacos
订单表 默认为空 库存表默认为100个库存
运行http://localhost:8190/order/add 结果如下 订单表新增一条记录库存表-1说明项目搭建成功
特殊情况
已知 order和stock是两个库 把order的controller代码改一下
package com.lcs.springcloud.controller;import com.lcs.springcloud.entity.OrderTbl;
import com.lcs.springcloud.feign.StockOpenFeign;
import com.lcs.springcloud.service.OrderService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;import java.math.BigDecimal;RestController
RequestMapping(/order)
public class OrderController {AutowiredOrderService orderService;AutowiredStockOpenFeign stockOpenFeign;RequestMapping(/add)Transactionalpublic String add(){OrderTbl orderTbl new OrderTbl();orderTbl.setProduct_id(10);orderTbl.setTotal_amount(new BigDecimal(3000));orderTbl.setStatu(0);//1. 插入订单orderService.insert(orderTbl);//2. 扣减库存String reduct stockOpenFeign.reduct(orderTbl.getProduct_id());// 3. 出现问题int a 1/0;return add order reduct;}
}都知道0不能作为分母必报错 大家说一下这个接口是多少 订单插入进行了回滚库存表进行扣减库存为什么 这是因为transaction事物是不支持跨库回滚的。
分布式事务
代码版本在上续上面做改动请保证上面能先运行后 再看该步骤
order-seata项目变动
pom.xml dependencygroupIdcom.alibaba.cloud/groupIdartifactIdspring-cloud-starter-alibaba-seata/artifactIdversion2.2.5.RELEASE/version/dependencydependencygroupIdcglib/groupIdartifactIdcglib/artifactIdversion3.3.0/version/dependency为什么加了一个cglib的包 报cg相关的一个错猜测估计是依赖冲突的问题查了一下项目依赖发现只有可能cglib的问题
application.yml
server:port: 8190spring:application:name: order-seatacloud:nacos:discovery:namespace: publicserver-addr: localhost:8848username: nacospassword: nacosalibaba:seata:tx-service-group: default_tx_groupdatasource:type: com.alibaba.druid.pool.DruidDataSourcedruid:db-type: mysqldriver-class-name: com.mysql.jdbc.Driverurl: jdbc:mysql://127.0.0.1:3306/seata_order?useUnicodetruecharacterEncodingutf-8allowMultiQueriestrueuseSSLfalseserverTimezoneAsia/ShanghaiallowPublicKeyRetrievaltrueuseCursorFetchtrueusername: rootpassword: 123456
mybatis:mapper-locations: classpath:mapper/*.xmlseata:registry:#配置seata的注册中心type: nacosnacos:### nacos服务器地址server-addr: localhost:8848username: nacospassword: nacos### nacos服务名application: seata-serverconfig:type: nacosnacos:### nacos服务器地址server-addr: localhost:8848username: nacospassword: nacosgroup: SEATA_GROUP为什么叫这个名字看自己seata-server的配置 这里标红的就是我们需要填写的名字在网上可以查到很多叫guangzhou的这是因为别人重命名咯
controller 注解改为GlobalTransactional表示是分布式事务
stock-seata项目变动
pom.xml dependencygroupIdcom.alibaba.cloud/groupIdartifactIdspring-cloud-starter-alibaba-seata/artifactIdversion2.2.5.RELEASE/version/dependencydependencygroupIdcglib/groupIdartifactIdcglib/artifactIdversion3.3.0/version/dependencyapplication.yml
server:port: 8200spring:application:name: stock-seatacloud:nacos:discovery:namespace: publicserver-addr: localhost:8848username: nacospassword: nacosalibaba:seata:tx-service-group: default_tx_groupdatasource:type: com.alibaba.druid.pool.DruidDataSourcedruid:db-type: mysqldriver-class-name: com.mysql.jdbc.Driverurl: jdbc:mysql://127.0.0.1:3306/seata_stock?useUnicodetruecharacterEncodingutf-8allowMultiQueriestrueuseSSLfalseserverTimezoneAsia/ShanghaiallowPublicKeyRetrievaltrueuseCursorFetchtrueusername: rootpassword: 123456
mybatis:mapper-locations: classpath:mapper/*.xmlseata:registry:#配置seata的注册中心type: nacosnacos:### nacos服务器地址server-addr: localhost:8848username: nacospassword: nacos### nacos服务名application: seata-serverconfig:type: nacosnacos:### nacos服务器地址server-addr: localhost:8848username: nacospassword: nacosgroup: SEATA_GROUP
跟order项目类似就是client跟seata以及nacos进行通信
脚本
CREATE TABLE undo_log (id bigint(20) NOT NULL AUTO_INCREMENT,branch_id bigint(20) NOT NULL,xid varchar(100) NOT NULL,context varchar(128) NOT NULL,rollback_info longblob NOT NULL,log_status int(11) NOT NULL,log_created datetime NOT NULL,log_modified datetime NOT NULL,ext varchar(100) DEFAULT NULL,PRIMARY KEY (id),UNIQUE KEY ux_undo_log (xid,branch_id)
) ENGINEInnoDB AUTO_INCREMENT3 DEFAULT CHARSETutf8;涉及到分布式事务的库都需要新增该undo-log得表他会记录修改前以及修改后的sql以便逆向回滚例如你执行了新增逆向就是删除
效果 order表 库存表 执行http://localhost:8190/order/add查看数据库出现异常后
之前使用transation是订单回滚库存减咯选择使用globaTransation注解订单回滚库存不变
分布式事务原理
nacos配置问题 启动后在bin下面多了一个store开头的文件夹why? 我不是改成db模式吗为什么配置没有生效查了半天才发现nacos的配置竟然是默认的
搜索store.mode*改成db
启动项目后竟然报数据库的一个错误怎么可能我数据库的配置都是copy的项目里面不可能出问题那原因只有一个就是nacos里面的初始化配置又有问题
修改nacos这三个的配置再启动项目seata得bin下面没有文件夹生成说明切换成db模式成功
seata的几个表都是什么情况 seata的表 这是seata的一个流程图 输入http://localhost:8190/order/add在进入方法的时候打入断点 global_table表生成了一个xid 拼接方式是ip端口再加一个唯一idxid 全局事务idapplication_id 应用idtransaction_service_group 分组transaction_name 事物加在那个方法上面以前有个版本会标注在具体类具体方法新版本后变动了好奇他底层是什么映射的知道的可以下方交流一下 断点执行到这里 branch_table 表新增了一条数据这个是分支Xid 订单库的undo-log也新增了一条数据 lock_table表变化会存储锁表的信息pk就是主键的id
#到order库调用该sql查看blob存放的内容
select CONVERT(t.rollback_info USING utf8) from undo_log t
如下图 因为是插入语句所以beforeImage之前是没有数据的afterImage存放的就是修改后的数据
断点走完后所有的seata表数据都会回滚如果遇到异常退出的情况请先清空表数据
代码下载