当前位置: 首页 > news >正文

网站建设实践报告小结域名网

网站建设实践报告小结,域名网,电子商务的网站开发的工作内容,公司网站建设的相关建议1. Seata 是什么? 由于业务和技术的发展,单体应用被拆分成微服务应用,原来的三个模块被拆分成三个独立的应用,分别使用三个独立的数据源,业务操作需要调用三个服务来完成。此时每个服务内部的数据一致性由本地事务来保证, 但是全…

1. Seata 是什么?

由于业务和技术的发展,单体应用被拆分成微服务应用,原来的三个模块被拆分成三个独立的应用,分别使用三个独立的数据源,业务操作需要调用三个服务来完成。此时每个服务内部的数据一致性由本地事务来保证, 但是全局的数据一致性问题没法保证。

Seata 是一款开源的分布式事务解决方案,致力于提供高性能和简单易用的分布式事务服务。Seata 将为用户提供了 AT、TCC、SAGA 和 XA 事务模式,为用户打造一站式的分布式解决方案。https://seata.io/zh-cn/docs/overview/what-is-seata.html
在这里插入图片描述

seata分布式事务处理过程的一ID+三组件模型:

  • Transaction ID XID 全局唯一的事务ID
  • 三组件概念
    • TC (Transaction Coordinator) - 事务协调者:维护全局和分支事务的状态,驱动全局事务提交或回滚。
    • TM (Transaction Manager) - 事务管理器:定义全局事务的范围:开始全局事务、提交或回滚全局事务。
    • RM (Resource Manager) - 资源管理器:管理分支事务处理的资源,与TC交谈以注册分支事务和报告分支事务的状态,并驱动分支事务提交或回滚。

处理过程:

  1. TM向TC申请开启一个全局事务,全局事务创建成功并生成一个全局唯一的XID;
  2. XID在微服务调用链路的上下文中传播;
  3. RM向TC注册分支事务,将其纳入XID对应全局事务的管辖;
  4. TM向TC发起针对XID的全局提交或回滚决议;
  5. TC调度XID下管辖的全部分支事务完成提交或回滚请求。

2. seata安装

Seata分TC、TM和RM三个角色,TC(Server端)为单独服务端部署,TM和RM(Client端)由业务系统集成。

本例前置条件:

  1. 默认nacos已经安装完成并启动,并开启了持久化配置
  2. 使用mysql8.0+数据库

2.1. Server端安装

seata1.5.2安装 + nacos2.1.1服务注册和配置中心集成
1. 下载seata 1.5.2: https://github.com/seata/seata/releases
在这里插入图片描述

2. 放在合适的路径下解压缩: 注意路径中一定不能出现中文和空格,否则会导致之后的git命令无法成功执行
在这里插入图片描述

3. 在数据库中创建全局事务所需要的表: 全局事务会话信息由3块内容构成,全局事务–>分支事务–>全局锁,对应表global_table、branch_table、lock_table

  1. 在数据库中创建一个名叫seata的数据库
    在这里插入图片描述

  2. 执行sql脚本创建数据表,该脚本可以在seata安装包中查看,或在git项目中https://github.com/seata/seata/blob/master/script/server/db/mysql.sql,获取最新的sql脚本。

在这里插入图片描述

  1. seata 1.5.0 新增了distributed_lock表用于 seata-server 异步任务调度,并将字符集改为了utf8mb4。
  2. 默认事务分组的由my_test_tx_group 修改为 default_tx_group
  3. 更多升级信息可以查看官方文档:https://seata.io/zh-cn/docs/ops/upgrade.html
-- -------------------------------- 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),`transaction_service_group` VARCHAR(32),`transaction_name`          VARCHAR(128),`timeout`                   INT,`begin_time`                BIGINT,`application_data`          VARCHAR(2000),`gmt_create`                DATETIME,`gmt_modified`              DATETIME,PRIMARY KEY (`xid`),KEY `idx_status_gmt_modified` (`status` , `gmt_modified`),KEY `idx_transaction_id` (`transaction_id`)
) ENGINE = InnoDBDEFAULT CHARSET = utf8mb4;-- the table to store BranchSession data
CREATE TABLE IF NOT EXISTS `branch_table`
(`branch_id`         BIGINT       NOT NULL,`xid`               VARCHAR(128) NOT NULL,`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),PRIMARY KEY (`branch_id`),KEY `idx_xid` (`xid`)
) ENGINE = InnoDBDEFAULT CHARSET = utf8mb4;-- the table to store lock data
CREATE TABLE IF NOT EXISTS `lock_table`
(`row_key`        VARCHAR(128) NOT NULL,`xid`            VARCHAR(128),`transaction_id` BIGINT,`branch_id`      BIGINT       NOT NULL,`resource_id`    VARCHAR(256),`table_name`     VARCHAR(32),`pk`             VARCHAR(36),`status`         TINYINT      NOT NULL DEFAULT '0' COMMENT '0:locked ,1:rollbacking',`gmt_create`     DATETIME,`gmt_modified`   DATETIME,PRIMARY KEY (`row_key`),KEY `idx_status` (`status`),KEY `idx_branch_id` (`branch_id`),KEY `idx_xid_and_branch_id` (`xid` , `branch_id`)
) ENGINE = InnoDBDEFAULT CHARSET = utf8mb4;CREATE TABLE IF NOT EXISTS `distributed_lock`
(`lock_key`       CHAR(20) NOT NULL,`lock_value`     VARCHAR(20) NOT NULL,`expire`         BIGINT,primary key (`lock_key`)
) ENGINE = InnoDBDEFAULT CHARSET = utf8mb4;INSERT INTO `distributed_lock` (lock_key, lock_value, expire) VALUES ('AsyncCommitting', ' ', 0);
INSERT INTO `distributed_lock` (lock_key, lock_value, expire) VALUES ('RetryCommitting', ' ', 0);
INSERT INTO `distributed_lock` (lock_key, lock_value, expire) VALUES ('RetryRollbacking', ' ', 0);
INSERT INTO `distributed_lock` (lock_key, lock_value, expire) VALUES ('TxTimeoutCheck', ' ', 0);
  1. 修改seata - config下的application.yaml配置文件,使用nacos作为服务注册发现中心和配置中心,其他详细配置可以参照seata提供的模板application.example.yml
    3.1. 在nacos中新建一个命名空间,并记录下空间ID
    3.2. 修改application.yml:主要修改项seata 下的 config、registry、store
server:port: 7091spring:application:name: seata-serverlogging:config: classpath:logback-spring.xmlfile:path: ${user.home}/logs/seataextend:logstash-appender:destination: 127.0.0.1:4560kafka-appender:bootstrap-servers: 127.0.0.1:9092topic: logback_to_logstashconsole:user:username: seatapassword: seataseata:config:# support: nacos, consul, apollo, zk, etcd3type: nacosnacos:server-addr: localhost:8848namespace: 704a579f-f1ef-45fd-818e-4e5c113ca50dgroup: SEATA_GROUPusername: nacospassword: nacos#data-id: seataServer.properties  registry:# support: nacos, eureka, redis, zk, consul, etcd3, sofatype: nacosnacos:application: seata-serverserver-addr: localhost:8848group: SEATA_GROUPnamespace: 704a579f-f1ef-45fd-818e-4e5c113ca50dcluster: defaultusername: nacospassword: nacos##if use MSE Nacos with auth, mutex with username/password attribute#access-key: ""#secret-key: ""store:# support: file 、 db 、 redismode: dbdb:datasource: druiddb-type: mysqldriver-class-name: com.mysql.cj.jdbc.Driverurl: jdbc:mysql://localhost:3306/seata?rewriteBatchedStatements=true&useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghaiuser: rootpassword: 123456min-conn: 1max-conn: 20global-table: global_tablebranch-table: branch_tablelock-table: lock_tabledistributed-lock-table: distributed_lockquery-limit: 100max-wait: 10000server:service-port: 8091 #If not configured, the default is '${server.port} + 1000'max-commit-retry-timeout: -1max-rollback-retry-timeout: -1rollback-retry-timeout-unlock-enable: falseenable-check-auth: trueenable-parallel-request-handle: trueretry-dead-threshold: 130000xaer-nota-retry-timeout: 60000undo:log-save-days: 7log-delete-period: 86400000session:branch-async-queue-size: 5000 #branch async remove queue sizeenable-branch-async-remove: false #enable to asynchronous remove branchSessionsecurity:secretKey: SeataSecretKey0c382ef121d778043159209298fd40bf3850a017tokenValidityInMilliseconds: 1800000ignore:urls: /,/**/*.css,/**/*.js,/**/*.html,/**/*.map,/**/*.svg,/**/*.png,/**/*.ico,/console-fe/public/**,/api/v1/auth/login

3.3. 修改config配置文件
将D:\seata\script\config-center下的config.txt复制一份到seata的目录下,与bin目录同级,并修改配置信息,主要修改store.mode和store.db(可以将不需要的配置信息删除掉,以防在nacos配置中心中产生太多无用的配置项,例如file和Redis的相关配置)
在这里插入图片描述

#For details about configuration items, see https://seata.io/zh-cn/docs/user/configurations.html
#Transport configuration, for client and server
transport.type=TCP
transport.server=NIO
transport.heartbeat=true
transport.enableTmClientBatchSendRequest=false
transport.enableRmClientBatchSendRequest=true
transport.enableTcServerBatchSendResponse=false
transport.rpcRmRequestTimeout=30000
transport.rpcTmRequestTimeout=30000
transport.rpcTcRequestTimeout=30000
transport.threadFactory.bossThreadPrefix=NettyBoss
transport.threadFactory.workerThreadPrefix=NettyServerNIOWorker
transport.threadFactory.serverExecutorThreadPrefix=NettyServerBizHandler
transport.threadFactory.shareBossWorker=false
transport.threadFactory.clientSelectorThreadPrefix=NettyClientSelector
transport.threadFactory.clientSelectorThreadSize=1
transport.threadFactory.clientWorkerThreadPrefix=NettyClientWorkerThread
transport.threadFactory.bossThreadSize=1
transport.threadFactory.workerThreadSize=default
transport.shutdown.wait=3
transport.serialization=seata
transport.compressor=none#Transaction routing rules configuration, only for the client
service.vgroupMapping.default_tx_group=default
#If you use a registry, you can ignore it
service.default.grouplist=127.0.0.1:8091
service.enableDegrade=false
service.disableGlobalTransaction=false#Transaction rule configuration, only for the client
client.rm.asyncCommitBufferLimit=10000
client.rm.lock.retryInterval=10
client.rm.lock.retryTimes=30
client.rm.lock.retryPolicyBranchRollbackOnConflict=true
client.rm.reportRetryCount=5
client.rm.tableMetaCheckEnable=true
client.rm.tableMetaCheckerInterval=60000
client.rm.sqlParserType=druid
client.rm.reportSuccessEnable=false
client.rm.sagaBranchRegisterEnable=false
client.rm.sagaJsonParser=fastjson
client.rm.tccActionInterceptorOrder=-2147482648
client.tm.commitRetryCount=5
client.tm.rollbackRetryCount=5
client.tm.defaultGlobalTransactionTimeout=60000
client.tm.degradeCheck=false
client.tm.degradeCheckAllowTimes=10
client.tm.degradeCheckPeriod=2000
client.tm.interceptorOrder=-2147482648
client.undo.dataValidation=true
client.undo.logSerialization=jackson
client.undo.onlyCareUpdateColumns=true
server.undo.logSaveDays=7
server.undo.logDeletePeriod=86400000
client.undo.logTable=undo_log
client.undo.compress.enable=true
client.undo.compress.type=zip
client.undo.compress.threshold=64k
#For TCC transaction mode
tcc.fence.logTableName=tcc_fence_log
tcc.fence.cleanPeriod=1h#Log rule configuration, for client and server
log.exceptionRate=100#Transaction storage configuration, only for the server. The file, DB, and redis configuration values are optional.
store.mode=db
store.lock.mode=db
store.session.mode=db
#Used for password encryption
store.publicKey=#These configurations are required if the `store mode` is `db`. If `store.mode,store.lock.mode,store.session.mode` are not equal to `db`, you can remove the configuration block.
store.db.datasource=druid
store.db.dbType=mysql
store.db.driverClassName=com.mysql.cj.jdbc.Driver
store.db.url=jdbc:mysql://localhost:3306/seata?rewriteBatchedStatements=true&useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai
store.db.user=root
store.db.password=123456
store.db.minConn=1
store.db.maxConn=20
store.db.globalTable=global_table
store.db.branchTable=branch_table
store.db.distributedLockTable=distributed_lock
store.db.queryLimit=100
store.db.lockTable=lock_table
store.db.maxWait=10000#Transaction rule configuration, only for the server
server.recovery.committingRetryPeriod=1000
server.recovery.asynCommittingRetryPeriod=1000
server.recovery.rollbackingRetryPeriod=1000
server.recovery.timeoutRetryPeriod=1000
server.maxCommitRetryTimeout=-1
server.maxRollbackRetryTimeout=-1
server.rollbackRetryTimeoutUnlockEnable=false
server.distributedLockExpireTime=10000
server.xaerNotaRetryTimeout=60000
server.session.branchAsyncQueueSize=5000
server.session.enableBranchAsyncRemove=false
server.enableParallelRequestHandle=false#Metrics configuration, only for the server
metrics.enabled=false
metrics.registryType=compact
metrics.exporterList=prometheus
metrics.exporterPrometheusPort=9898
  1. 注意需要将store.mode的三项DB改为小写db
  2. rewriteBatchedStatements=true,数据库链接中这一句是特别要加的,可以提升执行效率

3.4. 使用git将上面修改好的seata的配置导入nacos配置中心
复制D:\seata\script\config-center\nacos下的nacos-config.sh到D:\seata\conf文件夹下
在这里插入图片描述

在这里插入图片描述

右键启用git命令:输入以下命令并回车执行,等待数据同步即可
在这里插入图片描述

sh nacos-config.sh -h localhost -p 8848 -g SEATA_GROUP -t 704a579f-f1ef-45fd-818e-4e5c113ca50d -u nacos -w nacos

参数详情:
-h -p 指定nacos的端口地址;
-g 指定配置的分组,注意,是配置的分组;
-t 指定命名空间ID;
-u -w指定nacos的用户名和密码,使用nacos注册和配置认证的才需要指定。

导入成功后可以在nacos中查看到配置信息
在这里插入图片描述

2.2. Client端集成

基于springcloud分布式项目集成seata-Client端,首先需要搭建一个简单的测试服务环境:使用典型的订单系统,创建分布式微服务系统:共三个微服务模块

  • 订单管理:seata-order-service
  • 库存管理:seata-storage-service
  • 账户管理:seata-account-service

本例前置条件:
1. 使用openFeign作为微服务远程调用框架
2. 使用mybatis作为持久层框架
3. 使用nacos作为服务注册中心
4. 需要注意各框架版本,否则会出现版本冲突:详细信息查看https://github.com/alibaba/spring-cloud-alibaba/wiki/版本说明

2.2.1. 创建父Maven项目,进行依赖版本控制

主要的依赖项和使用版本:

  <properties><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding><maven.compiler.source>1.8</maven.compiler.source><maven.compiler.target>1.8</maven.compiler.target><junit.version>4.12</junit.version><log4j.version>1.2.17</log4j.version><lombok.version>1.16.18</lombok.version><mysql.version>8.0.23</mysql.version><druid.version>1.2.8</druid.version><mybatis.spring.boot.version>1.3.2</mybatis.spring.boot.version></properties><dependencyManagement><dependencies><!--springboot--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-dependencies</artifactId><version>2.3.12.RELEASE</version><type>pom</type><scope>import</scope></dependency><!--springCloud--><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-dependencies</artifactId><version>Hoxton.SR12</version><type>pom</type><scope>import</scope></dependency><!--springCloud alibaba--><dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-alibaba-dependencies</artifactId><version>2.2.9.RELEASE</version><type>pom</type><scope>import</scope></dependency><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>${mysql.version}</version></dependency><dependency><groupId>com.alibaba</groupId><artifactId>druid-spring-boot-starter</artifactId><version>${druid.version}</version></dependency><dependency><groupId>org.mybatis.spring.boot</groupId><artifactId>mybatis-spring-boot-starter</artifactId><version>${mybatis.spring.boot.version}</version></dependency><!--junit--><dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>${junit.version}</version></dependency><!--log4j--><dependency><groupId>log4j</groupId><artifactId>log4j</artifactId><version>${log4j.version}</version></dependency></dependencies></dependencyManagement>
2.2.2. 创建库存管理微服务:seata-storage-service

1. 添加pom依赖:在父项目下新建module seata-storage-service2002,并添加依赖

<artifactId>seata-storage-service2002</artifactId><dependencies><!--nacos--><dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId></dependency><!--seata--><dependency><groupId>io.seata</groupId><artifactId>seata-spring-boot-starter</artifactId><version>1.5.2</version></dependency><dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-seata</artifactId><version>2021.1</version><exclusions><exclusion><groupId>io.seata</groupId><artifactId>seata-spring-boot-starter</artifactId></exclusion></exclusions></dependency><!--web--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-actuator</artifactId></dependency><!--mysql connector--><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId></dependency><!--mysql druid--><dependency><groupId>com.alibaba</groupId><artifactId>druid-spring-boot-starter</artifactId></dependency><!--mybatis--><dependency><groupId>org.mybatis.spring.boot</groupId><artifactId>mybatis-spring-boot-starter</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><optional>true</optional></dependency></dependencies>

2. 修改application.yaml配置,以下为全部配置信息
需要先创建一个名叫seata_storage的数据库,以便数据库链接的配置:
在这里插入图片描述

server:port: 2002spring:application:name: seata-storage-servicecloud:nacos:discovery:server-addr: localhost:8848datasource:driver-class-name: com.mysql.cj.jdbc.Driverurl: jdbc:mysql://localhost:3306/seata_storage?useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghaiusername: rootpassword: 123456mybatis:mapper-locations: classpath:mapper/*.xml# seata 配置
seata:# seata配置中心tx-service-group: default_tx_groupconfig:type: nacosnacos:namespace: 704a579f-f1ef-45fd-818e-4e5c113ca50d# nacos配置中心地址server-addr: localhost:8848# 分组group: SEATA_GROUP# nacos的账号和密码userName: nacospassword: nacos# seata的注册中心registry:type: nacosnacos:application: seata-serverserver-addr: localhost:8848namespace: 704a579f-f1ef-45fd-818e-4e5c113ca50duserName: nacospassword: nacosservice:vgroup-mapping:default_tx_group: default

3. 编写业务代码
整体包结构:
在这里插入图片描述

domain包:
CommonResult:

package com.atguigu.alibaba.seata.domain;import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;/*** @author 强浩* @version 1.0.0* Copyright(c) YTANG All Rights Reserved* @className* @project 管理系统* @date 2022年10月17日*/
@Data
@AllArgsConstructor
@NoArgsConstructor
public class CommonResult<T> {private Integer code;private String  message;private T       data;public CommonResult(Integer code, String message){this(code,message,null);}
}

Storage:

package com.atguigu.alibaba.seata.domain;import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;/*** @author 强浩* @version 1.0.0* Copyright(c) YTANG All Rights Reserved* @className* @project 管理系统* @date 2022年10月18日*/
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Storage {private Long id;            //主键private Long productId;     //产品IDprivate Integer total;      //库存总量private Integer used;       //已用库存数量private Integer residue;    //剩余库存数量
}

数据库建表sql:在seata_storage下创建业务表

CREATE TABLE t_storage (
`id` BIGINT(11) NOT NULL AUTO_INCREMENT PRIMARY KEY,
`product_id` BIGINT(11) DEFAULT NULL COMMENT '产品id',
`total` INT(11) DEFAULT NULL COMMENT '总库存',
`used` INT(11) DEFAULT NULL COMMENT '已用库存',
`residue` INT(11) DEFAULT NULL COMMENT '剩余库存'
) ENGINE=INNODB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;INSERT INTO seata_storage.t_storage(`id`, `product_id`, `total`, `used`, `residue`)
VALUES ('1', '1', '100', '0','100');SELECT * FROM t_storage;

dao包:
StorageDao:

package com.atguigu.alibaba.seata.dao;import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;/*** @author 强浩* @version 1.0.0* Copyright(c) YTANG All Rights Reserved* @className* @project 管理系统* @date 2022年10月18日*/
@Mapper
public interface StorageDao {public void decrease(@Param("productId") Long productId, @Param("count") Integer count);
}

在resources下创建一个名叫mapper的文件夹,用来放mybatis的xml映射文件

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<!--Dao的全路径-->
<mapper namespace="com.atguigu.alibaba.seata.dao.StorageDao"><!--对应entity的全路径--><resultMap id="BaseResultMap" type="com.atguigu.alibaba.seata.domain.Storage"><id column="id" property="id" jdbcType="BIGINT"/><result column="product_id" property="productId" jdbcType="BIGINT"/><result column="total" property="total" jdbcType="INTEGER"/><result column="used" property="used" jdbcType="INTEGER"/><result column="residue" property="residue" jdbcType="INTEGER"/></resultMap><update id="decrease">updatet_storagesetused = used + #{count}, residue = residue - #{count}whereproduct_id = #{productId}</update>
</mapper>

service包:
StorageService:

package com.atguigu.alibaba.seata.service;import org.springframework.web.bind.annotation.RequestParam;/*** @author 强浩* @version 1.0.0* Copyright(c) YTANG All Rights Reserved* @className* @project 管理系统* @date 2022年10月18日*/
public interface StorageService {public void decrease(@RequestParam("productId") Long productId,@RequestParam("count") Integer count);
}

service.impl包:
StorageServiceImpl:

package com.atguigu.alibaba.seata.service.impl;import com.atguigu.alibaba.seata.dao.StorageDao;
import com.atguigu.alibaba.seata.service.StorageService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;import javax.annotation.Resource;/*** @author 强浩* @version 1.0.0* Copyright(c) YTANG All Rights Reserved* @className* @project 管理系统* @date 2022年10月18日*/
@Service
public class StorageServiceImpl implements StorageService {private static final Logger LOGGER = LoggerFactory.getLogger(StorageServiceImpl.class);@Resourceprivate StorageDao storageDao;@Overridepublic void decrease(Long productId, Integer count) {LOGGER.info("------->storage-service中扣减库存开始");storageDao.decrease(productId,count);LOGGER.info("------->storage-service中扣减库存结束");}
}

controller包:
StorageController:

package com.atguigu.alibaba.seata.controller;import com.atguigu.alibaba.seata.domain.CommonResult;
import com.atguigu.alibaba.seata.service.StorageService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;import javax.annotation.Resource;/*** @author 强浩* @version 1.0.0* Copyright(c) YTANG All Rights Reserved* @className* @project 管理系统* @date 2022年10月18日*/
@RestController
@Slf4j
public class StorageController {@Resourceprivate StorageService storageService;@RequestMapping("/storage/decrease")public CommonResult decrease(@RequestParam("productId") Long productId,@RequestParam("count") Integer count){storageService.decrease(productId, count);return new CommonResult(200,"扣减库存成功!");}
}

config包:配置mybatis的包扫描
MyBatisConfig:

package com.atguigu.alibaba.seata.config;import org.mybatis.spring.annotation.MapperScan;
import org.springframework.context.annotation.Configuration;/*** @author 强浩* @version 1.0.0* Copyright(c) YTANG All Rights Reserved* @className* @project 管理系统* @date 2022年10月18日*/
@Configuration
@MapperScan({"com.atguigu.alibaba.seata.dao"})
public class MyBatisConfig {}

主程序入口:

package com.atguigu.alibaba.seata;import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;/*** @author 强浩* @version 1.0.0* Copyright(c) YTANG All Rights Reserved* @className* @project 管理系统* @date 2022年10月18日*/
@EnableDiscoveryClient
@SpringBootApplication
public class StorageMain {public static void main(String[] args) {SpringApplication.run(StorageMain.class,args);}
}
2.2.3. 创建账户管理微服务:seata-account-service

1. 添加pom依赖:在父项目下新建module seata-account-service2003,并添加依赖

    <artifactId>seata-account-service2003</artifactId><dependencies><!--nacos--><dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId></dependency><!--seata--><dependency><groupId>io.seata</groupId><artifactId>seata-spring-boot-starter</artifactId><version>1.5.2</version></dependency><dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-seata</artifactId><version>2021.1</version><exclusions><exclusion><groupId>io.seata</groupId><artifactId>seata-spring-boot-starter</artifactId></exclusion></exclusions></dependency><!--web--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-actuator</artifactId></dependency><!--mysql connector--><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId></dependency><!--mysql druid--><dependency><groupId>com.alibaba</groupId><artifactId>druid-spring-boot-starter</artifactId></dependency><!--mybatis--><dependency><groupId>org.mybatis.spring.boot</groupId><artifactId>mybatis-spring-boot-starter</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><optional>true</optional></dependency></dependencies>

2. 修改application.yaml配置,以下为全部配置信息
需要先创建一个名叫seata_account的数据库,以便数据库链接的配置:
在这里插入图片描述

server:port: 2003spring:application:name: seata-account-servicecloud:nacos:discovery:server-addr: localhost:8848datasource:driver-class-name: com.mysql.cj.jdbc.Driverurl: jdbc:mysql://localhost:3306/seata_account?useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghaiusername: rootpassword: 123456mybatis:mapper-locations: classpath:mapper/*.xml# seata 配置
seata:# seata配置中心tx-service-group: default_tx_groupconfig:type: nacosnacos:namespace: 704a579f-f1ef-45fd-818e-4e5c113ca50d# nacos配置中心地址server-addr: localhost:8848# 分组group: SEATA_GROUP# nacos的账号和密码userName: nacospassword: nacos# seata的注册中心registry:type: nacosnacos:application: seata-serverserver-addr: localhost:8848namespace: 704a579f-f1ef-45fd-818e-4e5c113ca50duserName: nacospassword: nacosservice:vgroup-mapping:default_tx_group: default

3. 编写业务代码
整体包结构:
在这里插入图片描述

domain包:
CommonResult:

package com.atguigu.alibaba.seata.domain;import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;/*** @author 强浩* @version 1.0.0* Copyright(c) YTANG All Rights Reserved* @className* @project 管理系统* @date 2022年10月17日*/
@Data
@AllArgsConstructor
@NoArgsConstructor
public class CommonResult<T> {private Integer code;private String  message;private T       data;public CommonResult(Integer code, String message){this(code,message,null);}
}

Account:

package com.atguigu.alibaba.seata.domain;import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;import java.math.BigDecimal;/*** @author 强浩* @version 1.0.0* Copyright(c) YTANG All Rights Reserved* @className* @project 管理系统* @date 2022年10月18日*/
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Account {private Long id;            //主键private Long userId;        //用户IDprivate BigDecimal total;   //账户总额private BigDecimal used;    //已使用额度private BigDecimal residue; //剩余额度
}

数据库建表sql:在seata_account下创建业务表

CREATE TABLE t_account(`id` BIGINT(11) NOT NULL AUTO_INCREMENT PRIMARY KEY COMMENT 'id',`user_id` BIGINT(11) DEFAULT NULL COMMENT '用户id',`total` DECIMAL(10,0) DEFAULT NULL COMMENT '总额度',`used` DECIMAL(10,0) DEFAULT NULL COMMENT '已用余额',`residue` DECIMAL(10,0) DEFAULT '0' COMMENT '剩余可用额度'
) ENGINE=INNODB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;INSERT INTO seata_account.t_account(`id`, `user_id`, `total`, `used`, `residue`)
VALUES ('1', '1', '1000', '0', '1000');SELECT * FROM t_account;

dao包:
AccountDao:

package com.atguigu.alibaba.seata.dao;import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;import java.math.BigDecimal;/*** @author 强浩* @version 1.0.0* Copyright(c) YTANG All Rights Reserved* @className* @project 管理系统* @date 2022年10月18日*/
@Mapper
public interface AccountDao {public void decrease(@Param("userId") Long userId,@Param("money") BigDecimal money);
}

在resources下创建一个名叫mapper的文件夹,用来放mybatis的xml映射文件

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="com.atguigu.alibaba.seata.dao.AccountDao"><resultMap id="BaseResultMap" type="com.atguigu.alibaba.seata.domain.Account"><id property="id" column="id" jdbcType="BIGINT"/><result property="userId" column="user_id" jdbcType="BIGINT"/><result property="total" column="total" jdbcType="DECIMAL"/><result property="used" column="used" jdbcType="DECIMAL"/><result property="residue" column="residue" jdbcType="DECIMAL"/></resultMap><update id="decrease">updatet_accountsetresidue = residue - #{money}, used = used + #{money}whereuser_id = #{userId}</update>
</mapper>

service包:
AccountService:

package com.atguigu.alibaba.seata.service;import org.springframework.web.bind.annotation.RequestParam;import java.math.BigDecimal;/*** @author 强浩* @version 1.0.0* Copyright(c) YTANG All Rights Reserved* @className* @project 管理系统* @date 2022年10月18日*/
public interface AccountService {public void decrease (@RequestParam("userId") Long userId,@RequestParam("money") BigDecimal money);
}

service.impl包:
AccountServiceImpl:

package com.atguigu.alibaba.seata.service.impl;import com.atguigu.alibaba.seata.dao.AccountDao;
import com.atguigu.alibaba.seata.service.AccountService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;import javax.annotation.Resource;
import java.math.BigDecimal;/*** @author 强浩* @version 1.0.0* Copyright(c) YTANG All Rights Reserved* @className* @project 管理系统* @date 2022年10月18日*/
@Service
public class AccountServiceImpl implements AccountService {private static final Logger LOGGER = LoggerFactory.getLogger(AccountServiceImpl.class);@Resourceprivate AccountDao accountDao;@Overridepublic void decrease(Long userId, BigDecimal money) {LOGGER.info("------->Account-service中扣减金额开始");accountDao.decrease(userId, money);LOGGER.info("------->Account-service中扣减金额结束");}
}

controller包:

package com.atguigu.alibaba.seata.controller;import com.atguigu.alibaba.seata.domain.CommonResult;
import com.atguigu.alibaba.seata.service.AccountService;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;import javax.annotation.Resource;
import java.math.BigDecimal;/*** @author 强浩* @version 1.0.0* Copyright(c) YTANG All Rights Reserved* @className* @project 管理系统* @date 2022年10月18日*/
@RestController
public class AccountController {@Resourceprivate AccountService accountService;@RequestMapping("/account/decrease")public CommonResult decrease(@RequestParam("userId") Long userId,@RequestParam("money") BigDecimal money){accountService.decrease(userId, money);return new CommonResult(200,"扣减账户余额成功!");}
}

config包:
MyBatisConfig:

package com.atguigu.alibaba.seata.config;import org.mybatis.spring.annotation.MapperScan;
import org.springframework.context.annotation.Configuration;/*** @author 强浩* @version 1.0.0* Copyright(c) YTANG All Rights Reserved* @className* @project 管理系统* @date 2022年10月18日*/
@Configuration
@MapperScan({"com.atguigu.alibaba.seata.dao"})
public class MyBatisConfig {}

主程序入口:

package com.atguigu.alibaba.seata;import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;/*** @author 强浩* @version 1.0.0* Copyright(c) YTANG All Rights Reserved* @className* @project 管理系统* @date 2022年10月18日*/
@EnableDiscoveryClient
@SpringBootApplication
public class AccountMain {public static void main(String[] args) {SpringApplication.run(AccountMain.class,args);}
}
2.2.4. 创建订单管理微服务:seata-order-service

1. 添加pom依赖:在父项目下新建module seata-order-service2001,并添加依赖

    <artifactId>seata-order-service2001</artifactId><dependencies><!--nacos--><dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId></dependency><!--seata 官方文档推荐依赖添加方式--><dependency><groupId>io.seata</groupId><artifactId>seata-spring-boot-starter</artifactId><version>1.5.2</version></dependency><dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-seata</artifactId><version>2021.1</version><exclusions><exclusion><groupId>io.seata</groupId><artifactId>seata-spring-boot-starter</artifactId></exclusion></exclusions></dependency><!--openfeign--><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-openfeign</artifactId><version>2.2.0.RELEASE</version></dependency><!--web-actuator--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-actuator</artifactId></dependency><!--mysql-druid--><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId></dependency><dependency><groupId>com.alibaba</groupId><artifactId>druid-spring-boot-starter</artifactId><version>1.1.10</version></dependency><!--mybatis--><dependency><groupId>org.mybatis.spring.boot</groupId><artifactId>mybatis-spring-boot-starter</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><optional>true</optional></dependency></dependencies>

2. 修改application.yaml配置,以下为全部配置信息
需要先创建一个名叫seata_order的数据库,以便数据库链接的配置:
在这里插入图片描述

server:port: 2001spring:application:name: seata-order-servicecloud:nacos:discovery:server-addr: localhost:8848datasource:driver-class-name: com.mysql.cj.jdbc.Driverurl: jdbc:mysql://localhost:3306/seata_order?useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghaiusername: rootpassword: 123456mybatis:mapper-locations: classpath:mapper/*.xml# seata 配置
seata:# seata配置中心tx-service-group: default_tx_groupconfig:type: nacosnacos:namespace: 704a579f-f1ef-45fd-818e-4e5c113ca50d# nacos配置中心地址server-addr: localhost:8848# 分组group: SEATA_GROUP# nacos的账号和密码userName: nacospassword: nacos# seata的注册中心registry:type: nacosnacos:application: seata-serverserver-addr: localhost:8848namespace: 704a579f-f1ef-45fd-818e-4e5c113ca50duserName: nacospassword: nacosservice:vgroup-mapping:default_tx_group: default

3. 编写业务代码
整体包结构:
在这里插入图片描述

domain包:
CommonResult:

package com.atguigu.alibaba.seata.domain;import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;/*** @author 强浩* @version 1.0.0* Copyright(c) YTANG All Rights Reserved* @className* @project 管理系统* @date 2022年10月17日*/
@Data
@AllArgsConstructor
@NoArgsConstructor
public class CommonResult<T> {private Integer code;private String  message;private T       data;public CommonResult(Integer code, String message){this(code,message,null);}
}

Order:也就是entity,和数据库字段对应

package com.atguigu.alibaba.seata.domain;import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;import java.math.BigDecimal;/*** @author 强浩* @version 1.0.0* Copyright(c) YTANG All Rights Reserved* @className* @project 管理系统* @date 2022年10月17日*/
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Order {private Long id;private Long userId;private Long productId;private Integer count;private BigDecimal money;private Integer status; //订单状态:0:创建中;1:已完结
}

数据库建表sql:在数据库中新建一个名叫seata-order的数据库,并创建业务表

CREATE TABLE t_order (`id` BIGINT(11) NOT NULL AUTO_INCREMENT PRIMARY KEY,`user_id` BIGINT(11) DEFAULT NULL COMMENT '用户id',`product_id` BIGINT(11) DEFAULT NULL COMMENT '产品id',`count` INT(11) DEFAULT NULL COMMENT '数量',`money` DECIMAL(11,0) DEFAULT NULL COMMENT '金额',`status` INT(1) DEFAULT NULL COMMENT '订单状态: 0:创建中; 1:已完结'
) ENGINE=INNODB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;SELECT * FROM t_order;

dao包:
OrderDao:

package com.atguigu.alibaba.seata.dao;import com.atguigu.alibaba.seata.domain.Order;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;/*** @author 强浩* @version 1.0.0* Copyright(c) YTANG All Rights Reserved* @className* @project 管理系统* @date 2022年10月17日*/
@Mapper
public interface OrderDao {//1 新建订单public void create(Order order);//2 修改订单状态,从零改为1public void update(@Param("userId") Long userId, @Param("status") Integer status);
}

在resources下创建一个名叫mapper的文件夹,用来放mybatis的xml映射文件

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<!--Dao的全路径-->
<mapper namespace="com.atguigu.alibaba.seata.dao.OrderDao"><!--对应entity的全路径--><resultMap id="BaseResultMap" type="com.atguigu.alibaba.seata.domain.Order"><id column="id" property="id" jdbcType="BIGINT"/><result column="user_id" property="userId" jdbcType="BIGINT"/><result column="product_id" property="productId" jdbcType="BIGINT"/><result column="count" property="count" jdbcType="INTEGER"/><result column="money" property="money" jdbcType="DECIMAL"/><result column="status" property="status" jdbcType="INTEGER"/></resultMap><insert id="create">insert into t_order (id,user_id,product_id,count,money,status)values (null,#{userId},#{productId},#{count},#{money},0);</insert><update id="update">update t_order set status = 1where user_id=#{userId} and status = #{status};</update>
</mapper>

service包:因为订单服务需要调用库存和账户服务,所以需要使用openFeign进行远程调用服务接口,并且需要先行将这两个服务的接口创建好
StorageService:

package com.atguigu.alibaba.seata.service;import com.atguigu.alibaba.seata.domain.CommonResult;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.stereotype.Service;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;/*** @author 强浩* @version 1.0.0* Copyright(c) YTANG All Rights Reserved* @className* @project 管理系统* @date 2022年10月17日*/
@Service("storageService")
@FeignClient(value = "seata-storage-service")
public interface StorageService {@PostMapping(value = "/storage/decrease")CommonResult decrease(@RequestParam("productId") Long productId, @RequestParam("count") Integer count);
}

AccountService:

package com.atguigu.alibaba.seata.service;import com.atguigu.alibaba.seata.domain.CommonResult;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.stereotype.Service;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;import java.math.BigDecimal;/*** @author 强浩* @version 1.0.0* Copyright(c) YTANG All Rights Reserved* @className* @project 管理系统* @date 2022年10月17日*/
@Service("accountService")
@FeignClient(value = "seata-account-service")
public interface AccountService {@PostMapping(value = "/account/decrease")CommonResult decrease(@RequestParam("userId") Long userId,@RequestParam("money") BigDecimal money);
}

OrderService:

package com.atguigu.alibaba.seata.service;import com.atguigu.alibaba.seata.domain.Order;/*** @author 强浩* @version 1.0.0* Copyright(c) YTANG All Rights Reserved* @className* @project 管理系统* @date 2022年10月17日*/
public interface OrderService {void create(Order order);
}

service.impl包:
OrderServiceImpl:

package com.atguigu.alibaba.seata.service.impl;import com.atguigu.alibaba.seata.dao.OrderDao;
import com.atguigu.alibaba.seata.domain.Order;
import com.atguigu.alibaba.seata.service.AccountService;
import com.atguigu.alibaba.seata.service.OrderService;
import com.atguigu.alibaba.seata.service.StorageService;
import io.seata.spring.annotation.GlobalTransactional;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;import javax.annotation.Resource;/*** @author 强浩* @version 1.0.0* Copyright(c) YTANG All Rights Reserved* @className* @project 管理系统* @date 2022年10月17日*/
@Service
@Slf4j
public class OrderServiceImpl implements OrderService {@Resourceprivate OrderDao orderDao;@Resourceprivate StorageService storageService;@Resourceprivate AccountService accountService;@Override@GlobalTransactionalpublic void create(Order order) {log.info("----->开始新建订单");//1 新建订单orderDao.create(order);//2 扣减库存log.info("----->订单微服务开始调用库存,做扣减Count");storageService.decrease(order.getProductId(),order.getCount());log.info("----->订单微服务开始调用库存,做扣减end");//3 扣减账户log.info("----->订单微服务开始调用账户,做扣减Money");accountService.decrease(order.getUserId(),order.getMoney());log.info("----->订单微服务开始调用账户,做扣减end");//4 修改订单状态,从零到1,1代表已经完成log.info("----->修改订单状态开始");orderDao.update(order.getUserId(),0);log.info("----->修改订单状态结束");}
}

controller包:
OrderSeataController:

package com.atguigu.alibaba.seata.controller;import com.atguigu.alibaba.seata.domain.CommonResult;
import com.atguigu.alibaba.seata.domain.Order;
import com.atguigu.alibaba.seata.service.OrderService;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;import javax.annotation.Resource;/*** @author 强浩* @version 1.0.0* Copyright(c) YTANG All Rights Reserved* @className* @project 管理系统* @date 2022年10月17日*/
@RestController
public class OrderSeataController {@Resourceprivate OrderService orderService;@GetMapping("/order/create")public CommonResult create(Order order){orderService.create(order);return new CommonResult(200,"订单创建成功");}
}

config包:

package com.atguigu.alibaba.seata.config;import org.mybatis.spring.annotation.MapperScan;
import org.springframework.context.annotation.Configuration;/*** @author 强浩* @version 1.0.0* Copyright(c) YTANG All Rights Reserved* @className* @project 管理系统* @date 2022年10月17日*/
@Configuration
@MapperScan({"com.atguigu.alibaba.seata.dao"})
public class MyBatisConfig {}

主程序入口:

package com.atguigu.alibaba.seata;import io.seata.spring.annotation.datasource.EnableAutoDataSourceProxy;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.openfeign.EnableFeignClients;/*** @author 强浩* @version 1.0.0* Copyright(c) YTANG All Rights Reserved* @className* @project 管理系统* @date 2022年10月17日*/
@SpringBootApplication
@EnableDiscoveryClient
@EnableFeignClients
@EnableAutoDataSourceProxy
public class OrderMain {public static void main(String[] args) {SpringApplication.run(OrderMain.class,args);}
}
2.2.5. 集成Seata - Client

1. 添加seata依赖(编写业务代码时已经添加完毕)
2. 在所有需要进行全局事务管理的业务数据库下新建undo_log表、配置参数(仅AT模式)
在这里插入图片描述

-- the table to store seata xid data
-- 0.7.0+ add context
-- you must to init this sql for you business databese. the seata server not need it.
-- 此脚本必须初始化在你当前的业务数据库中,用于AT 模式XID记录。与server端无关(注:业务数据库)
-- 注意此处0.3.0+ 增加唯一索引 ux_undo_log
drop table `undo_log`;
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`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;

3. 数据源代理(不支持自动和手动配置并存):我这里使用的是seata-starter,默认开启了自动数据源代理,无需修改
4. 初始化GlobalTransactionScanner:自动,引入seata-spring-boot-starter、spring-cloud-starter-alibaba-seata等jar,无需修改
5. 实现xid跨服务传递:自动 springCloud用户可以引入spring-cloud-starter-alibaba-seata,内部已经实现xid传递,无需修改
官方部署指南:https://seata.io/zh-cn/docs/ops/deploy-guide-beginner.html

2.2.6. 业务使用

注解拦截:全局事务
在需要进行全局事务管理的入口接口上标注: @GlobalTransactional,例:

@Service
@Slf4j
public class OrderServiceImpl implements OrderService {@Resourceprivate OrderDao orderDao;@Resourceprivate StorageService storageService;@Resourceprivate AccountService accountService;@Override@GlobalTransactionalpublic void create(Order order) {log.info("----->开始新建订单");//1 新建订单orderDao.create(order);//2 扣减库存log.info("----->订单微服务开始调用库存,做扣减Count");storageService.decrease(order.getProductId(),order.getCount());log.info("----->订单微服务开始调用库存,做扣减end");//3 扣减账户log.info("----->订单微服务开始调用账户,做扣减Money");accountService.decrease(order.getUserId(),order.getMoney());log.info("----->订单微服务开始调用账户,做扣减end");//4 修改订单状态,从零到1,1代表已经完成log.info("----->修改订单状态开始");orderDao.update(order.getUserId(),0);log.info("----->修改订单状态结束");}
}
2.2.7. 测试

1. 启动seata-server:双击bin下的seata-server.bat
2. 启动三个微服务:
发送请求:这时应该可以正常创建数据并扣减数据
http://localhost:2001/order/create?userId=1&productId=1&count=10&money=100
3. 先不添加@GlobalTransactional注解
在关闭account账户服务的情况下,发送请求:这时数据库应该创建了订单信息和扣减了库存,但账户没有扣减,出现了数据的不一致
http://localhost:2001/order/create?userId=1&productId=1&count=10&money=100
4. 添加@GlobalTransactional注解,在关闭account账户服务的情况下
发送请求:这时数据库应该不会创建任何数据加粗样式

http://www.tj-hxxt.cn/news/68426.html

相关文章:

  • 文山网站建设联系电话seo综合查询工具有什么功能
  • 三网合一网站建设方案沈阳seo代理计费
  • b2c网站开发注意事项网站制作策划
  • wordpress无插件实现网站地图付费推广
  • 东城手机网站制作超八成搜索网站存在信息泄露问题
  • 怎么做带网站连接的表格seo网站优化方案摘要
  • 马鞍山网站设计制作市场调研报告500字
  • 自己怎么建个优惠网站百度一下搜索网页
  • dedecms中英文网站营销网站建设价格
  • 自己做的旅游网站简介怎样推广自己的网站
  • 站长工具seo综合查询烟雨楼网络营销类型
  • 景乔网站建设百度免费注册
  • wordpress用户密码找回seo与sem的关系
  • wordpress mysql 端口博客seo教程
  • 怎么做属于自己的域名网站seo教学网站
  • 网站制作国内知名企业网站创建的流程是什么
  • 做推广网站排名怎么在百度上发帖推广
  • 神州行套餐sem优化师
  • 怎么做网站h汉狮怎样交换友情链接
  • 网站建设的数据导入导出广州网络推广服务商
  • 专业的网站制作专业公司网页怎么做
  • 日本政府网站建设经验怎么写软文
  • 毕业设计代做网站 知乎网站推广的基本方法有哪些
  • 男男做暧暧视频网站网店推广平台有哪些
  • 济南建网站公司排行榜关键词推广营销
  • 企业网站定制多少钱seo工程师是做什么的
  • 东莞常平邮政编码查询seo外链发布技巧
  • 网站建设的开发程序360搜索优化
  • 网站建设方面的优劣势分析东莞网站建设推广平台
  • 前端优化网站排行榜软件