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

怎么可以黑网站域名58首码项目网

怎么可以黑网站域名,58首码项目网,软件开发模型的优缺点,龙岗个性化网站建设价格低文章目录 一、分布式事务存在的问题二、分布式事务理论三、认识SeataSeata分布式事务解决方案1、XA模式2、AT模式3、SAGA模式4.SAGA模式优缺点#xff1a;5.四种模式对比 四、微服务整合Seata AT案例Seata配置微服务整合2.1、父工程项目创建引入依赖 2.2、Eureka集群搭建2.3、… 文章目录 一、分布式事务存在的问题二、分布式事务理论三、认识SeataSeata分布式事务解决方案1、XA模式2、AT模式3、SAGA模式4.SAGA模式优缺点5.四种模式对比 四、微服务整合Seata AT案例Seata配置微服务整合2.1、父工程项目创建引入依赖 2.2、Eureka集群搭建2.3、搭建账户微服务2.3.1 新建seata-account-service微服务2.3.2引入依赖2.3.3seata事务用到的表2.3.4seata微服务配置2.3.5yml配置seata事务2.3.6数据源交给seata去代理2.3.7主启动类去掉默认自动加载数据源2.3.8业务数据dbDOdaoservicemapper.xmlcontroller 2.4、搭建库存微服务2.4.1 新建seata-storage-service微服务2.4.2引入依赖2.4.3seata事务用到的表2.4.4seata微服务配置2.4.5yml配置seata事务2.4.6数据源交给seata去代理2.4.7主启动类去掉默认自动加载数据源2.4.8业务数据dbDOdaoservicemapper.xmlcontroller 2.5、搭建订单微服务2.5.1 新建seata-order-service微服务2.5.2引入依赖2.5.3seata事务用到的表2.5.4seata微服务配置2.5.5yml配置seata事务2.5.6数据源交给seata去代理2.5.7主启动类去掉默认自动加载数据源2.5.8业务数据dbDOdaoserviceservice实现类添加GlobalTransactionalmapper.xmlfegincontroller 2.6、测试 一、分布式事务存在的问题 在分布式系统下一个业务跨越多个服务或数据源每个服务都是一个分支事务要保证所有分支事务最终状态一致这样的事务就是分布式事务。 二、分布式事务理论 、CAP定理 CAP是指Consistency(一致性Availability可用性Partition tolerance分区容错性1、一致性 用户访问分布式系统中的任意节点得到的数据必须是一致的。 节点1的数据一旦发生修改节点2的数据必须进行同步与节点1的数据保持一致。 2、可用性 用户访问集群中的任意健康节点时必须能得到响应而不是超时或者拒绝。 当节点3发生故障时就会对请求进行阻塞或者拒绝此时节点3就是不可用的。 3、分区容错性 分区因为网络故障或其它原因导致分布式系统中的部分系欸DNA与其它节点失去连接形成独立分区。 容错在集群出现分区时整个系统也要持续对外提供服务。 起初节点1、2、3是互相连接的即任意节点数据发生变化其余两个节点的数据也将进行同步修改但是假设节点3与其他两个节点的网络连接断开了但是节点本身并没有故障就会形成新的分区此时一旦有人对节点2的数据进行了修改并将修改信息同步到了节点1此时用户访问不同的节点假设访问节点1之后我们又访问了节点3此时拿到的结果就是不一致的。此时就不满足一致性如果我们非要满足一致性我们怎么办让节点3进入短暂的禁止访问状态等待和节点2的网络通信回复在此期间对于到来的一切请求都进行拒绝或者阻塞这样一来确实一致性问题得到了解决但是我们又说了可用性即系统健康时就必须对请求做出响应此时我们的节点3只是和其余两个节点不通并没有不健康所以这就是一种悖论我们只能在一致性和可用性之间做出抉择 CAP定理的主要内容分布式系统节点通过网络连接一定会出现分区问题P当分区出现时系统的一致性C和可用性A就无法同时满足CP保证了系统的一致性但是牺牲了系统的可用性。 AP保证了系统的可用性但是牺牲了系统的一致性。 BASE理论 BASE理论是对CAP的一种解决思路包含三个思想Basically Available 基本可用分布式系统在出现故障时允许损失部分可用性即保证核心可用。Soft State软状态在一定时间内允许出现中间状态比如临时的不一致状态。Eventually Consistent最终一致性虽然无法保证强一致性但是在软状态结束后最终达到数据一致。而分布式事务最大的问题是各个子事务的一致性问题因此可以借鉴CAP定理和BASE理论 AP模式各子事务分别执行和提交允许出现结果不一致软状态然后采用弥补措施恢复数据即可实现最终一致。 CP模式各个子事务执行后互相等待同时提交同时回滚达成强一致。但事务等待过程中处于弱可用状态。解决分布式事务各个子系统之间必须能感知到彼此的事务状态才能保证状态一致因此需要一个事务协调者来协调每一个事务的参与者子系统事务。 这里的子系统事务称为分支事务有关联的各个分支事务在一起称为全局事务。 三、认识Seata Seata事务管理中有三个重要的角色 TC (Transaction Coordinator) - 事务协调者维护全局和分支事务的状态协调全局事务提交或回滚。 TM (Transaction Manager) - 事务管理器定义全局事务的范围、开始全局事务、提交或回滚全局事务。 RM (Resource Manager) - 资源管理器管理分支事务处理的资源与TC交谈以注册分支事务和报告分支事务的状态并驱动分支事务提交或回滚。Seata分布式事务解决方案 Seata提供了四种不同的分布式事务解决方案XA模式强一致性分阶段事务模式牺牲了一定的可用性无业务侵入TCC模式最终一致的分阶段事务模式有业务侵入AT模式最终一致的分阶段事务模式无业务侵入也是Seata的默认模式SAGA模式长事务模式有业务侵入1、XA模式 XA 规范 是 X/Open 组织定义的分布式事务处理DTPDistributed Transaction Processing标准XA 规范 描述了全局的TM与局部的RM之间的接口几乎所有主流的数据库都对 XA 规范 提供了支持。 XA是规范目前主流的数据库都实现了这种规范实现的原理都是基于两阶段提交。 正常情况异常情况 一阶段 事务协调者通知每个事务参与者分别执行本地事务 本地事务执行完成后向事务协调者告知事务的执行状态此时本地事务并没有提交继续持有数据库锁 二阶段 事务协调者根据一阶段的报告判断下一步操作①、如果一阶段所有分支事务都执行成功则告知所有事务参与者提交事务。②、如果一阶段任意一个事务失败则告知所有事务参与者回滚事务。下面我们来看看Seata当中的XA模型 RM一阶段的工作 注册分支事务到TC 执行分支业务sql但不提交 报告执行状态给TCTC二阶段的工作 TC检测各分支事务的执行状态a.如果都成功通知所有RM提交事务b.如果有失败通知所有RM回滚事务RM二阶段的工作 接收TC的指令提交或回滚事务。XA模式的优缺点 优点事务的强一致性满足ACID原则。常用数据库都支持实现简单并且没有代码侵入。缺点因为一阶段需要锁定数据库资源等待二阶段结束才会释放性能较差。依赖关系型数据库实现事务。如何利用Seata实现XA模式 1、修改配置文件每个参与事务的微服务开启XA模式 seata:data-source-proxy-mode: XA2、给发起全局事务的入口方法添加GlobalTransactional注解 3、重启服务测试 2、AT模式 AT模式是对XA模式的弊端进行了完善执行事务完并不会持续占有数据库资源。我们来看看AT模式具体是怎么做的 在XA模式当中一阶段分支事务执行完事务后会等待TC的通知进行事务的提交或者事务的回滚等待过程中会持有DB锁防止其他事务进行操作这样会大大降低性能在AT模式下分支事务不需要等待TC的通知即可提交事务但是会生成一份数据快照undo_log该快照记录了数据修改前和修改后的值当TC通知分支事务进行事务提交或者回滚时如果是提交分支事务则仅需要删除生成的快照即可如果是回滚则需要根据快照当中的信息恢复数据。 AT模式下该分支事务的执行流程如下 一阶段 1TM发起并注册全局事务到TC 2TM调用分支事务 3分支事务准备执行业务SQL 4RM拦截业务SQL根据where条件查询原始数据形成快照 5RM执行业务SQL提交本地事务释放DB锁此时money90 6RM报告本地事务状态给TC 二阶段 1TM通知TC事务结束 2TC检查分支事务状态 a)都成功则通知RM删除快照 b)有失败通知RM根据快照恢复数据 流程图 XA模式与AT模式的区别 XA模式一阶段不提交事务锁定资源AT模式一阶段直接提交不锁定资源。 XA模式依赖数据库机制实现回滚AT模式利用数据快照实现数据回滚。 XA模式强一致AT模式最终一致AT模式的弊端——脏写问题 解决方案就是引入全局锁的概念在释放DB锁之前先要拿到全局锁避免同一时刻有另外一个事务来操作当前持有的数据。 这个全局锁就限制了哪个事务可以操作该数据当事务1执行业务SQL前会先获取全局锁TC就会进行记录此时事务1释放DB锁去等待TC的通知删除快照或根据快照修复数据事务2拿到了DB锁开始执行业务SQL当事务2尝试获取全局锁时就会发现获取不到因为全局锁现在被事务1所持有此时假设恰好TC告知事务1进行数据回滚事务1则会重新获取DB锁但是DB锁此时被事务2所持有这样就形成了死锁怎么办事务2在尝试获取一段时间全局锁后一直拿不到就会放弃获取全局锁此时事务1就拿到了DB锁进行快照修复即可。前提是两个事务均是由seata控制的事务才会这样。假设事务2不是由seata控制的事务将会是怎样的 我们上面说过事务1记录undo_log时会记录数据修改前后的值当我们进行数据恢复时发现money此时为80此时需要我们进行报警处理人工的根据undo_log当中的数据进行数据恢复。 AT模式的优点一阶段完成直接提交事务释放数据库资源性能比较好利用全局锁实现读写隔离没有代码侵入框架自动完成回滚和提交 AT模式的缺点两阶段之间属于软状态属于最终一致框架的快照功能会影响性能但比XA模式要好很多3、TCC模式 TCC模式与AT模式非常相似每阶段都是独立事务区别在于TCC是通过人工代码控制来实现数据恢复需要实现三个方法 Try资源的检测和预留。 Confirm完成资源操作业务要求 Try 成功 Confirm 一定要能成功。 Cancel预留资源释放可以理解为try的反向操作。举例一个扣减用户余额的业务。假设账户A原来余额是100需要余额扣减30元。 阶段一 Try 检查余额是否充足如果充足则冻结金额增加30元可用余额扣除30 初始余额 此时总金额 冻结金额 可用金额数量依然是100不变。事务直接提交无需等待其它事务。 阶段二Confirm)假如要提交Confirm则冻结金额扣减30 确认可以提交不过之前可用金额已经扣减过了这里只要清除冻结金额就好了 此时总金额 冻结金额 可用金额 0 70 70元 阶段二(Canncel)如果要回滚Cancel则冻结金额扣减30可用余额增加30需要回滚那么就要释放冻结金额恢复可用金额 TCC模型 可以看到TCC模式和AT模式极其相似但是区别在于AT模式采用全局锁undo_log的方式进行事务提交和回滚这里我们不再使用锁而是使用try-confirm-cancel的方式对操作进行记录。当TC通知分支事务可以提交的时候分支事务直接执行confirm方法即可通知回滚时则执行cancel方法 TCC模式的优缺点 TCC模式的每个阶段是做什么的 Try资源检查和预留Confirm业务执行和提交Cancel预留资源的释放TCC的优点是什么 一阶段完成直接提交事务释放数据库资源性能好 相比AT模型无需生成快照无需使用全局锁性能最强 不依赖数据库事务而是依赖补偿操作可以用于非事务型数据库 TCC的缺点是什么 有代码侵入需要人为编写try、Confirm和Cancel接口太麻烦 软状态事务是最终一致 需要考虑Confirm和Cancel的失败情况做好幂等处理 TCC模式的两个重要问题事务悬挂和空回滚 事务悬挂对于已经空回滚的业务之前被阻塞的try操作恢复继续执行try就永远不可能confirm或cancel 事务一直处于中间状态这就是业务悬挂。 执行try操作时应当判断cancel是否已经执行过了如果已经执行应当阻止空回滚后的try操作避免悬挂 空回滚当某分支事务的try阶段阻塞时可能导致全局事务超时而触发二阶段的cancel操作。在未执行try操作时先执行了cancel操作这时cancel不能做回滚就是空回滚。 执行cancel操作时应当判断try是否已经执行如果尚未执行则应该空回 3、SAGA模式 原理 在 Saga 模式下分布式事务内有多个参与者每一个参与者都是一个冲正补偿服务需要用户根据业务场景实现其正向操作和逆向回滚操作。 分布式事务执行过程中依次执行各参与者的正向操作如果所有正向操作均执行成功那么分布式事务提交。如果任何一个正向操作执行失败那么分布式事务会去退回去执行前面各参与者的逆向回滚操作回滚已提交的参与者使分布式事务回到初始状态。 Saga也分为两个阶段 一阶段直接提交本地事务 二阶段成功则什么都不做失败则通过编写补偿业务来回滚 4.SAGA模式优缺点 优点 事务参与者可以基于事件驱动实现异步调用吞吐高 一阶段直接提交事务无锁性能好 不用编写TCC中的三个阶段实现简单缺点 软状态持续时间不确定时效性差 没有锁没有事务隔离会有脏写 5.四种模式对比 四、微服务整合Seata AT案例 分布式事务和传统形式的事务区别有什么众所周知我们采用微服务框架开发项目时不同服务之间通过相互调用的方式完成业务处理用以下案例来描述分布式业务存在的问题 假设我们此时现在有一个系统其中包括下单系统、用户系统、仓库系统。当我们进行下单时就需要创建订单信息同时需要对用户的余额进行扣减还需要对仓储系统的商品数量进行减少由于每个系统分别负责一部分的业务且其拥有独立的数据库信息因此我们就会有三个事务订单创建、余额扣减、商品剩余量扣减。 Seata配置 4.1.1Seata下载 下载Seata服务端压缩包https://github.com/seata/seata/releases 4.1.2、修改conf目录中 flie.conf 文件 修改事务日志存储模式为 db 及数据库连接信息且新增service模块如下 store {## store mode: file、db、redis## 使用数据库mode dbdb {## the implement of javax.sql.DataSource, such as DruidDataSource(druid)/BasicDataSource(dbcp)/HikariDataSource(hikari) etc.datasource druid## mysql/oracle/postgresql/h2/oceanbase etc.dbType mysqldriverClassName com.mysql.cj.jdbc.Driver## 数据库地址url jdbc:mysql://localhost:3306/seata?useUnicodetrueallowPublicKeyRetrievaltruecharacterEncodingutf-8useSSLfalseserverTimezoneGMT%2b8## 数据库账号user root## 数据库密码 password 123456minConn 5maxConn 100globalTable global_tablebranchTable branch_tablelockTable lock_tablequeryLimit 100maxWait 5000}} 4.1.3、修改conf目录中 registry.conf文件 这里使用eureka注册中心 registry {type eurekaeureka {serviceUrl http://eureka7001.com:7001/eureka/,http://eureka7002.com:7002/eureka/ #改成自己的eureka注册中心地址application seata-server #本客户端注册到eureka的微服务名称weight 1} } 4.1.4、初始化seata数据库 由于我们使用了db模式存储事务日志所以我们需要创建一个seata数据库Seata数据库表初始化脚本 -- -------------------------------- 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 (xid) ) 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);DROP TABLE IF EXISTS 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) ) ENGINEInnoDB AUTO_INCREMENT1 DEFAULT CHARSETutf8; 微服务整合 2.1、父工程项目创建 引入依赖 ?xml version1.0 encodingUTF-8?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/xsd/maven-4.0.0.xsdmodelVersion4.0.0/modelVersiongroupIdcom.my.springcloud/groupIdartifactIdcloud-seata/artifactIdversion1.0-SNAPSHOT/versionpackagingpom/packagingmodulesmoduleseata-account-service/modulemoduleseata-order-service/modulemoduleseata-storage-service/modulemodulecloud-eureka-server7001/modulemodulecloud-eureka-server7002/modulemodulecloud-gateway-gateway/module/modules!-- 统一管理jar包版本 --propertiesproject.build.sourceEncodingUTF-8/project.build.sourceEncodingmaven.compiler.source1.8/maven.compiler.sourcemaven.compiler.target1.8/maven.compiler.targetjunit.version4.12/junit.versionlog4j.version1.2.17/log4j.versionlombok.version1.16.18/lombok.versionmysql.version8.0.28/mysql.versiondruid.version1.2.4/druid.versionmybatis.spring.boot.version2.0.0/mybatis.spring.boot.version/properties!-- 子模块继承之后,提供作用锁定版本子modlue不用写groupId和version --dependencyManagementdependencies!--spring boot 2.3.2--dependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-dependencies/artifactIdversion2.3.2.RELEASE/versiontypepom/typescopeimport/scope/dependency!--spring cloud Hoxton.SR9--dependencygroupIdorg.springframework.cloud/groupIdartifactIdspring-cloud-dependencies/artifactIdversionHoxton.SR9/versiontypepom/typescopeimport/scope/dependency!--spring cloud alibaba 2.2.5.RELEASE--dependencygroupIdcom.alibaba.cloud/groupIdartifactIdspring-cloud-alibaba-dependencies/artifactIdversion2.2.5.RELEASE/versiontypepom/typescopeimport/scope/dependencydependencygroupIdorg.mybatis.spring.boot/groupIdartifactIdmybatis-spring-boot-starter/artifactIdversion${mybatis.spring.boot.version}/version/dependencydependencygroupIdmysql/groupIdartifactIdmysql-connector-java/artifactIdversion${mysql.version}/version/dependencydependencygroupIdcom.alibaba/groupIdartifactIddruid-spring-boot-starter/artifactIdversion${druid.version}/version/dependencydependencygroupIdorg.projectlombok/groupIdartifactIdlombok/artifactIdversion${lombok.version}/versionoptionaltrue/optional/dependencydependencygroupIdlog4j/groupIdartifactIdlog4j/artifactIdversion${log4j.version}/version/dependencydependencygroupIdjunit/groupIdartifactIdjunit/artifactIdversion${junit.version}/version/dependency!--seata依赖--dependencygroupIdcom.alibaba.cloud/groupIdartifactIdspring-cloud-starter-alibaba-seata/artifactIdversion2021.1/versionexclusions!--版本较低1.3.0因此排除--exclusionartifactIdseata-spring-boot-starter/artifactIdgroupIdio.seata/groupId/exclusion/exclusions/dependencydependencygroupIdio.seata/groupIdartifactIdseata-spring-boot-starter/artifactIdversion1.4.1/version/dependency/dependencies/dependencyManagementbuildpluginsplugingroupIdorg.springframework.boot/groupIdartifactIdspring-boot-maven-plugin/artifactIdconfigurationaddResourcestrue/addResources/configuration/plugin/plugins/build /project 2.2、Eureka集群搭建 eureka搭建 添加链接描述 2.3、搭建账户微服务 2.3.1 新建seata-account-service微服务 2.3.2引入依赖 dependenciesdependencygroupIdorg.springframework.cloud/groupIdartifactIdspring-cloud-starter-netflix-eureka-client/artifactId/dependency!--seata依赖--dependencygroupIdcom.alibaba.cloud/groupIdartifactIdspring-cloud-starter-alibaba-seata/artifactIdexclusionsexclusionartifactIdseata-all/artifactIdgroupIdio.seata/groupId/exclusion/exclusions/dependencydependencygroupIdio.seata/groupIdartifactIdseata-spring-boot-starter/artifactIdversion1.4.1/version/dependency!--feign--dependencygroupIdorg.springframework.cloud/groupIdartifactIdspring-cloud-starter-openfeign/artifactId/dependencydependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-web/artifactId/dependencydependencygroupIdorg.mybatis.spring.boot/groupIdartifactIdmybatis-spring-boot-starter/artifactId/dependencydependencygroupIdmysql/groupIdartifactIdmysql-connector-java/artifactId/dependencydependencygroupIdcom.alibaba/groupIdartifactIddruid-spring-boot-starter/artifactId/dependencydependencygroupIdorg.projectlombok/groupIdartifactIdlombok/artifactIdoptionaltrue/optional/dependencydependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-test/artifactIdscopetest/scope/dependency/dependencies2.3.3seata事务用到的表 DROP TABLE IF EXISTS 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) ) ENGINEInnoDB AUTO_INCREMENT1 DEFAULT CHARSETutf8; 2.3.4seata微服务配置 在resources 下 新增2个配置文件 file.conf 和 registry.conffile.conf transport {# tcp udt unix-domain-sockettype TCP#NIO NATIVEserver NIO#enable heartbeatheartbeat true# the client batch send request enableenableClientBatchSendRequest true#thread factory for nettythreadFactory {bossThreadPrefix NettyBossworkerThreadPrefix NettyServerNIOWorkerserverExecutorThread-prefix NettyServerBizHandlershareBossWorker falseclientSelectorThreadPrefix NettyClientSelectorclientSelectorThreadSize 1clientWorkerThreadPrefix NettyClientWorkerThread# netty boss thread size,will not be used for UDTbossThreadSize 1#auto default pin or 8workerThreadSize default}shutdown {# when destroy server, wait secondswait 3}serialization seatacompressor none } service {#这里注意,等号前后都是配置,前面是yml里配置的事务组,后面是register.conf里定义的seata-servervgroupMapping.my_test_tx_group seata-server#only support when registry.typefile, please dont set multiple addressesseata_tc_server.grouplist 127.0.0.1:8091#degrade, current not supportenableDegrade false#disable seatadisableGlobalTransaction false } client {rm {asyncCommitBufferLimit 10000lock {retryInterval 10retryTimes 30retryPolicyBranchRollbackOnConflict true}reportRetryCount 5tableMetaCheckEnable falsereportSuccessEnable false}tm {commitRetryCount 5rollbackRetryCount 5}undo {dataValidation truelogSerialization jacksonlogTable undo_log}log {exceptionRate 100} } registry.conf registry {# file 、nacos 、eureka、redis、zk、consul、etcd3、sofa## 注册中心为eurekatype eurekaloadBalance RandomLoadBalanceloadBalanceVirtualNodes 10nacos {application seata-serverserverAddr 127.0.0.1:8848group SEATA_GROUPnamespace cluster defaultusername password }eureka {## eureka地址serviceUrl http://eureka7001.com:7001/eureka/,http://eureka7002.com:7002/eureka/application seata-serverweight 1}redis {serverAddr localhost:6379db 0password 123456cluster defaulttimeout 0}zk {cluster defaultserverAddr 127.0.0.1:2181sessionTimeout 6000connectTimeout 2000username password }consul {cluster defaultserverAddr 127.0.0.1:8500}etcd3 {cluster defaultserverAddr http://localhost:2379}sofa {serverAddr 127.0.0.1:9603application defaultregion DEFAULT_ZONEdatacenter DefaultDataCentercluster defaultgroup SEATA_GROUPaddressWaitTime 3000}file {name file.conf} }config {# file、nacos 、apollo、zk、consul、etcd3type filenacos {serverAddr 127.0.0.1:8848namespace group SEATA_GROUPusername password }consul {serverAddr 127.0.0.1:8500}apollo {appId seata-serverapolloMeta http://192.168.1.204:8801namespace applicationapolloAccesskeySecret }zk {serverAddr 127.0.0.1:2181sessionTimeout 6000connectTimeout 2000username password }etcd3 {serverAddr http://localhost:2379}file {name file.conf} } 2.3.5yml配置seata事务 需要在yml配置文件加上配置项指明当前服务使用了 seata分布式事务组件且需要加入的分布式事务组是哪个 server:# 服务器的HTTP端口默认为80port: 2000# Spring配置 spring:application:#微服务名称name: seata-account-servicedatasource:type: com.alibaba.druid.pool.DruidDataSource # 当前数据源操作类型driverClassName: com.mysql.cj.jdbc.Driver # mysql驱动包url: jdbc:mysql://localhost:3306/seata_account?useUnicodetruecharacterEncodingutf8zeroDateTimeBehaviorconvertToNulluseSSLtrueserverTimezoneGMT%2B8 # 数据库名称username: rootpassword: 123456seata:enabled: trueapplication-id: ${spring.application.name}tx-service-group: seata-serverenable-auto-data-source-proxy: trueservice:default: 127.0.0.1:8091vgroup-mapping:seata-server: defaultconfig:type: filefile:name: file.confregistry:type: filefile:name: file# MyBatis mybatis:# 所有Entity别名类所在包typeAliasesPackage: com.my.springcloud.domain# 配置mapper的扫描找到所有的mapper.xml映射文件mapperLocations: classpath*:mapper/*Mapper.xml# 加载全局的配置文件# configLocation: classpath:mybatis/mybatis-config.xml# eureka客户端配置 eureka:client:#表示是否向Eureka注册中心注册自己register-with-eureka: truefetch-registry: true # false表示自己就是注册中心,我的职责就是维护服务实例,并不需要去检索服务service-url:#defaultZone: http://eureka7001.com:7001/eureka/,http://eureka7002.com:7002/eureka/defaultZone: http://eureka7001.com:7001/eureka/,http://eureka7002.com:7002/eureka/instance:#向注册中心注册服务IDinstance-id: ${spring.cloud.client.ip-address}:${server.port}prefer-ip-address: true #显示IP地址# Eureka客户端向服务端发送心跳的时间间隔,单位为秒(默认是30秒)lease-renewal-interval-in-seconds: 30#Eureka服务端在收到最后一次心跳后等待时间上限,单位为秒(默认是90秒)超时将剔除服务lease-expiration-duration-in-seconds: 90logging:level:io:seata: info2.3.6数据源交给seata去代理 import com.alibaba.druid.pool.DruidDataSource; import io.seata.rm.datasource.DataSourceProxy; import org.apache.ibatis.session.SqlSessionFactory; import org.mybatis.spring.SqlSessionFactoryBean; import org.mybatis.spring.transaction.SpringManagedTransactionFactory; import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.core.io.support.PathMatchingResourcePatternResolver;import javax.sql.DataSource;/*** 使用Seata对数据源进行代理*/ Configuration public class DataSourceProxyConfig {//加载数据源BeanConfigurationProperties(prefix spring.datasource)public DataSource druidDataSource() {return new DruidDataSource();}Value(${mybatis.mapperLocations})private String mapperLocations;Beanpublic DataSource dataSourceProxy(DataSource dataSource) {return new DataSourceProxy(dataSource);}Beanpublic SqlSessionFactory sqlSessionFactoryBean(DataSource dataSourceProxy) throws Exception {SqlSessionFactoryBean sqlSessionFactoryBean new SqlSessionFactoryBean();sqlSessionFactoryBean.setDataSource(dataSourceProxy);sqlSessionFactoryBean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources(mapperLocations));sqlSessionFactoryBean.setTransactionFactory(new SpringManagedTransactionFactory());return sqlSessionFactoryBean.getObject();}}2.3.7主启动类去掉默认自动加载数据源 import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration; import org.springframework.cloud.netflix.eureka.EnableEurekaClient; import org.springframework.cloud.openfeign.EnableFeignClients;EnableEurekaClient //开启Eureka的客户端服务,将会自动注册到注册中心 SpringBootApplication(exclude DataSourceAutoConfiguration.class) public class SeataAccountApp {public static void main(String[] args) {SpringApplication.run(SeataAccountApp.class, args);} } 2.3.8业务数据 db (1)创建account数据库 (2)在数据库下创建seata_account表 DROP TABLE IF EXISTS t_account; CREATE TABLE t_account (id BIGINT(20) NOT NULL AUTO_INCREMENT comment 主键,user_id BIGINT(20) comment 用户id,total NUMERIC(20) comment 总额度,used NUMERIC(20) comment 已用额度,residue NUMERIC(20) comment 剩余额度,PRIMARY KEY (id) ) ENGINEInnoDB AUTO_INCREMENT1 DEFAULT CHARSETutf8 comment 账户表;DO Data AllArgsConstructor NoArgsConstructor public class Account {private Long id;/*** 用户id*/private Long userId;/*** 总额度*/private BigDecimal total;/*** 已用额度*/private BigDecimal used;/*** 剩余额度*/private BigDecimal residue; }dao Mapper public interface AccountDao {/*** 扣减账户余额*/void decrease(Param(userId) Long userId, Param(money) BigDecimal money); } service public interface AccountService {/*** 扣减账户余额* param userId 用户id* param money 金额*/void decrease(RequestParam(userId) Long userId, RequestParam(money) BigDecimal money); } mapper.xml ?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.my.springcloud.dao.AccountDaoresultMap idBaseResultMap typecom.my.springcloud.domain.Accountid columnid propertyid jdbcTypeBIGINT/result columnuser_id propertyuserId jdbcTypeBIGINT/result columntotal propertytotal jdbcTypeDECIMAL/result columnused propertyused jdbcTypeDECIMAL/result columnresidue propertyresidue jdbcTypeDECIMAL//resultMapupdate iddecreaseUPDATE t_accountSETresidue residue - #{money},used used #{money}WHEREuser_id #{userId};/update/mapper controller public class AccountController {ResourceAccountService accountService;/*** 扣减账户余额*/RequestMapping(/account/decrease)public CommonResult decrease(RequestParam(userId) Long userId, RequestParam(money) BigDecimal money) {accountService.decrease(userId, money);return new CommonResult(200, 扣减账户余额成功);} }2.4、搭建库存微服务 2.4.1 新建seata-storage-service微服务 2.4.2引入依赖 dependenciesdependencygroupIdorg.springframework.cloud/groupIdartifactIdspring-cloud-starter-netflix-eureka-client/artifactId/dependency!--seata依赖--dependencygroupIdcom.alibaba.cloud/groupIdartifactIdspring-cloud-starter-alibaba-seata/artifactIdexclusionsexclusionartifactIdseata-all/artifactIdgroupIdio.seata/groupId/exclusion/exclusions/dependencydependencygroupIdio.seata/groupIdartifactIdseata-spring-boot-starter/artifactIdversion1.4.1/version/dependency!--feign--dependencygroupIdorg.springframework.cloud/groupIdartifactIdspring-cloud-starter-openfeign/artifactId/dependencydependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-web/artifactId/dependencydependencygroupIdorg.mybatis.spring.boot/groupIdartifactIdmybatis-spring-boot-starter/artifactId/dependencydependencygroupIdmysql/groupIdartifactIdmysql-connector-java/artifactId/dependencydependencygroupIdcom.alibaba/groupIdartifactIddruid-spring-boot-starter/artifactId/dependencydependencygroupIdorg.projectlombok/groupIdartifactIdlombok/artifactIdoptionaltrue/optional/dependencydependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-test/artifactIdscopetest/scope/dependency/dependencies2.4.3seata事务用到的表 DROP TABLE IF EXISTS 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) ) ENGINEInnoDB AUTO_INCREMENT1 DEFAULT CHARSETutf8; 2.4.4seata微服务配置 在resources 下 新增2个配置文件 file.conf 和 registry.conffile.conf transport {# tcp udt unix-domain-sockettype TCP#NIO NATIVEserver NIO#enable heartbeatheartbeat true# the client batch send request enableenableClientBatchSendRequest true#thread factory for nettythreadFactory {bossThreadPrefix NettyBossworkerThreadPrefix NettyServerNIOWorkerserverExecutorThread-prefix NettyServerBizHandlershareBossWorker falseclientSelectorThreadPrefix NettyClientSelectorclientSelectorThreadSize 1clientWorkerThreadPrefix NettyClientWorkerThread# netty boss thread size,will not be used for UDTbossThreadSize 1#auto default pin or 8workerThreadSize default}shutdown {# when destroy server, wait secondswait 3}serialization seatacompressor none } service {#这里注意,等号前后都是配置,前面是yml里配置的事务组,后面是register.conf里定义的seata-servervgroupMapping.my_test_tx_group seata-server#only support when registry.typefile, please dont set multiple addressesseata_tc_server.grouplist 127.0.0.1:8091#degrade, current not supportenableDegrade false#disable seatadisableGlobalTransaction false } client {rm {asyncCommitBufferLimit 10000lock {retryInterval 10retryTimes 30retryPolicyBranchRollbackOnConflict true}reportRetryCount 5tableMetaCheckEnable falsereportSuccessEnable false}tm {commitRetryCount 5rollbackRetryCount 5}undo {dataValidation truelogSerialization jacksonlogTable undo_log}log {exceptionRate 100} } registry.conf registry {# file 、nacos 、eureka、redis、zk、consul、etcd3、sofa## 注册中心为eurekatype eurekaloadBalance RandomLoadBalanceloadBalanceVirtualNodes 10nacos {application seata-serverserverAddr 127.0.0.1:8848group SEATA_GROUPnamespace cluster defaultusername password }eureka {## eureka地址serviceUrl http://eureka7001.com:7001/eureka/,http://eureka7002.com:7002/eureka/application seata-serverweight 1}redis {serverAddr localhost:6379db 0password 123456cluster defaulttimeout 0}zk {cluster defaultserverAddr 127.0.0.1:2181sessionTimeout 6000connectTimeout 2000username password }consul {cluster defaultserverAddr 127.0.0.1:8500}etcd3 {cluster defaultserverAddr http://localhost:2379}sofa {serverAddr 127.0.0.1:9603application defaultregion DEFAULT_ZONEdatacenter DefaultDataCentercluster defaultgroup SEATA_GROUPaddressWaitTime 3000}file {name file.conf} }config {# file、nacos 、apollo、zk、consul、etcd3type filenacos {serverAddr 127.0.0.1:8848namespace group SEATA_GROUPusername password }consul {serverAddr 127.0.0.1:8500}apollo {appId seata-serverapolloMeta http://192.168.1.204:8801namespace applicationapolloAccesskeySecret }zk {serverAddr 127.0.0.1:2181sessionTimeout 6000connectTimeout 2000username password }etcd3 {serverAddr http://localhost:2379}file {name file.conf} } 2.4.5yml配置seata事务 需要在yml配置文件加上配置项指明当前服务使用了 seata分布式事务组件且需要加入的分布式事务组是哪个 server:# 服务器的HTTP端口默认为80port: 2002#Spring配置 spring:application:name: seata-storage-service#----------------------------数据源----------------------------datasource:type: com.alibaba.druid.pool.DruidDataSourcedriverClassName: com.mysql.cj.jdbc.Driverurl: jdbc:mysql://localhost:3306/seata_storage?useUnicodetruecharacterEncodingutf8zeroDateTimeBehaviorconvertToNulluseSSLtrueserverTimezoneGMT%2B8username: rootpassword: 123456druid:initial-size: 5min-idle: 5max-active: 20test-while-idle: truetest-on-borrow: falsetest-on-return: falsepool-prepared-statements: truemax-pool-prepared-statement-per-connection-size: 20max-wait: 60000time-between-eviction-runs-millis: 60000min-evictable-idle-time-millis: 30000filters: statasync-init: true#----------------------------seata---------------------------- seata:enabled: trueapplication-id: ${spring.application.name}tx-service-group: seata-serverenable-auto-data-source-proxy: trueservice:default: 127.0.0.1:8091vgroup-mapping:seata-server: defaultconfig:type: filefile:name: file.confregistry:type: filefile:name: file# eureka客户端配置 eureka:client:#表示是否向Eureka注册中心注册自己register-with-eureka: truefetch-registry: true # false表示自己就是注册中心,我的职责就是维护服务实例,并不需要去检索服务service-url:#defaultZone: http://eureka7001.com:7001/eureka/,http://eureka7002.com:7002/eureka/defaultZone: http://eureka7001.com:7001/eureka/,http://eureka7002.com:7002/eureka/instance:#向注册中心注册服务IDinstance-id: ${spring.cloud.client.ip-address}:${server.port}prefer-ip-address: true #显示IP地址# Eureka客户端向服务端发送心跳的时间间隔,单位为秒(默认是30秒)lease-renewal-interval-in-seconds: 30#Eureka服务端在收到最后一次心跳后等待时间上限,单位为秒(默认是90秒)超时将剔除服务lease-expiration-duration-in-seconds: 90#MyBatis mybatis:#所有Entity别名类所在包,多个路径用逗号分割typeAliasesPackage: com.my.springcloud.domain# 配置mapper的扫描找到所有的mapper,多个目录用逗号或者分号分隔mapperLocations: classpath*:mapper/*Mapper.xml# 加载全局的配置文件# configLocation: classpath:mybatis/mybatis-config.xml 2.4.6数据源交给seata去代理 import com.alibaba.druid.pool.DruidDataSource; import io.seata.rm.datasource.DataSourceProxy; import org.apache.ibatis.session.SqlSessionFactory; import org.mybatis.spring.SqlSessionFactoryBean; import org.mybatis.spring.transaction.SpringManagedTransactionFactory; import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.core.io.support.PathMatchingResourcePatternResolver;import javax.sql.DataSource;/*** 使用Seata对数据源进行代理*/ Configuration public class DataSourceProxyConfig {//加载数据源BeanConfigurationProperties(prefix spring.datasource)public DataSource druidDataSource() {return new DruidDataSource();}Value(${mybatis.mapperLocations})private String mapperLocations;Beanpublic DataSource dataSourceProxy(DataSource dataSource) {return new DataSourceProxy(dataSource);}Beanpublic SqlSessionFactory sqlSessionFactoryBean(DataSource dataSourceProxy) throws Exception {SqlSessionFactoryBean sqlSessionFactoryBean new SqlSessionFactoryBean();sqlSessionFactoryBean.setDataSource(dataSourceProxy);sqlSessionFactoryBean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources(mapperLocations));sqlSessionFactoryBean.setTransactionFactory(new SpringManagedTransactionFactory());return sqlSessionFactoryBean.getObject();}}2.4.7主启动类去掉默认自动加载数据源 EnableEurekaClient //开启Eureka的客户端服务,将会自动注册到注册中心 SpringBootApplication(exclude DataSourceAutoConfiguration.class) public class SeataStorageApp {public static void main(String[] args) {SpringApplication.run(SeataStorageApp.class, args);} } 2.4.8业务数据 db (1)创建storage数据库 (2)在数据库下创建seata_storage表 DROP TABLE IF EXISTS t_storage; CREATE TABLE t_storage (id bigint(20) NOT NULL AUTO_INCREMENT comment 主键,product_id bigint(30) comment 产品id,total INTEGER(20) comment 总库存,used INTEGER(20) comment 已用库存,residue INTEGER(30) comment 剩余库存,PRIMARY KEY (id) ) ENGINEInnoDB AUTO_INCREMENT1 DEFAULT CHARSETutf8 comment 库存表;DO Data public class Storage {private Long id;/*** 产品id*/private Long productId;/*** 总库存*/private Integer total;/*** 已用库存*/private Integer used;/*** 剩余库存*/private Integer residue; }dao Mapper public interface StorageDao {//扣减库存void decrease(Param(productId) Long productId, Param(count) Integer count); } service public interface StorageService {/*** 扣减库存*/void decrease(Long productId, Integer count); } mapper.xml ?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.my.springcloud.dao.StorageDaoresultMap idBaseResultMap typecom.my.springcloud.domain.Storageid columnid propertyid jdbcTypeBIGINT/result columnproduct_id propertyproductId jdbcTypeBIGINT/result columntotal propertytotal jdbcTypeINTEGER/result columnused propertyused jdbcTypeINTEGER/result columnresidue propertyresidue jdbcTypeINTEGER//resultMapupdate iddecreaseUPDATEt_storageSET used used #{count},residue residue - #{count}WHERE product_id #{productId}/update /mapper controller RestController public class StorageController {Autowiredprivate StorageService storageService;/*** 扣减库存*/RequestMapping(/storage/decrease)public CommonResult decrease(Long productId, Integer count) {storageService.decrease(productId, count);return new CommonResult(200, 扣减库存成功);} }2.5、搭建订单微服务 2.5.1 新建seata-order-service微服务 2.5.2引入依赖 dependenciesdependencygroupIdorg.springframework.cloud/groupIdartifactIdspring-cloud-starter-netflix-eureka-client/artifactId/dependency!--seata依赖--dependencygroupIdcom.alibaba.cloud/groupIdartifactIdspring-cloud-starter-alibaba-seata/artifactIdexclusionsexclusionartifactIdseata-all/artifactIdgroupIdio.seata/groupId/exclusion/exclusions/dependencydependencygroupIdio.seata/groupIdartifactIdseata-spring-boot-starter/artifactIdversion1.4.1/version/dependency!--feign--dependencygroupIdorg.springframework.cloud/groupIdartifactIdspring-cloud-starter-openfeign/artifactId/dependencydependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-web/artifactId/dependencydependencygroupIdorg.mybatis.spring.boot/groupIdartifactIdmybatis-spring-boot-starter/artifactId/dependencydependencygroupIdmysql/groupIdartifactIdmysql-connector-java/artifactId/dependencydependencygroupIdcom.alibaba/groupIdartifactIddruid-spring-boot-starter/artifactId/dependencydependencygroupIdorg.projectlombok/groupIdartifactIdlombok/artifactIdoptionaltrue/optional/dependencydependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-test/artifactIdscopetest/scope/dependency!-- 添加 httpclient 框架依赖 --dependencygroupIdio.github.openfeign/groupIdartifactIdfeign-httpclient/artifactId/dependencydependencygroupIdio.github.openfeign/groupIdartifactIdfeign-okhttp/artifactId/dependency/dependencies2.5.3seata事务用到的表 DROP TABLE IF EXISTS 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) ) ENGINEInnoDB AUTO_INCREMENT1 DEFAULT CHARSETutf8; 2.5.4seata微服务配置 在resources 下 新增2个配置文件 file.conf 和 registry.conffile.conf transport {# tcp udt unix-domain-sockettype TCP#NIO NATIVEserver NIO#enable heartbeatheartbeat true# the client batch send request enableenableClientBatchSendRequest true#thread factory for nettythreadFactory {bossThreadPrefix NettyBossworkerThreadPrefix NettyServerNIOWorkerserverExecutorThread-prefix NettyServerBizHandlershareBossWorker falseclientSelectorThreadPrefix NettyClientSelectorclientSelectorThreadSize 1clientWorkerThreadPrefix NettyClientWorkerThread# netty boss thread size,will not be used for UDTbossThreadSize 1#auto default pin or 8workerThreadSize default}shutdown {# when destroy server, wait secondswait 3}serialization seatacompressor none } service {#这里注意,等号前后都是配置,前面是yml里配置的事务组,后面是register.conf里定义的seata-servervgroupMapping.my_test_tx_group seata-server#only support when registry.typefile, please dont set multiple addressesseata_tc_server.grouplist 127.0.0.1:8091#degrade, current not supportenableDegrade false#disable seatadisableGlobalTransaction false } client {rm {asyncCommitBufferLimit 10000lock {retryInterval 10retryTimes 30retryPolicyBranchRollbackOnConflict true}reportRetryCount 5tableMetaCheckEnable falsereportSuccessEnable false}tm {commitRetryCount 5rollbackRetryCount 5}undo {dataValidation truelogSerialization jacksonlogTable undo_log}log {exceptionRate 100} } registry.conf registry {# file 、nacos 、eureka、redis、zk、consul、etcd3、sofa## 注册中心为eurekatype eurekaloadBalance RandomLoadBalanceloadBalanceVirtualNodes 10nacos {application seata-serverserverAddr 127.0.0.1:8848group SEATA_GROUPnamespace cluster defaultusername password }eureka {## eureka地址serviceUrl http://eureka7001.com:7001/eureka/,http://eureka7002.com:7002/eureka/application seata-serverweight 1}redis {serverAddr localhost:6379db 0password 123456cluster defaulttimeout 0}zk {cluster defaultserverAddr 127.0.0.1:2181sessionTimeout 6000connectTimeout 2000username password }consul {cluster defaultserverAddr 127.0.0.1:8500}etcd3 {cluster defaultserverAddr http://localhost:2379}sofa {serverAddr 127.0.0.1:9603application defaultregion DEFAULT_ZONEdatacenter DefaultDataCentercluster defaultgroup SEATA_GROUPaddressWaitTime 3000}file {name file.conf} }config {# file、nacos 、apollo、zk、consul、etcd3type filenacos {serverAddr 127.0.0.1:8848namespace group SEATA_GROUPusername password }consul {serverAddr 127.0.0.1:8500}apollo {appId seata-serverapolloMeta http://192.168.1.204:8801namespace applicationapolloAccesskeySecret }zk {serverAddr 127.0.0.1:2181sessionTimeout 6000connectTimeout 2000username password }etcd3 {serverAddr http://localhost:2379}file {name file.conf} } 2.5.5yml配置seata事务 需要在yml配置文件加上配置项指明当前服务使用了 seata分布式事务组件且需要加入的分布式事务组是哪个 server:# 服务器的HTTP端口默认为80port: 2001#Spring配置 spring:application:name: seata-order-service#----------------------------数据源----------------------------datasource:type: com.alibaba.druid.pool.DruidDataSourcedriverClassName: com.mysql.cj.jdbc.Driverurl: jdbc:mysql://localhost:3306/seata_order?useUnicodetruecharacterEncodingutf8zeroDateTimeBehaviorconvertToNulluseSSLtrueserverTimezoneGMT%2B8username: rootpassword: 123456druid:initial-size: 5min-idle: 5max-active: 20test-while-idle: truetest-on-borrow: falsetest-on-return: falsepool-prepared-statements: truemax-pool-prepared-statement-per-connection-size: 20max-wait: 60000time-between-eviction-runs-millis: 60000min-evictable-idle-time-millis: 30000filters: statasync-init: true#----------------------------seata---------------------------- seata:enabled: trueapplication-id: ${spring.application.name}tx-service-group: seata-serverenable-auto-data-source-proxy: trueservice:default: 127.0.0.1:8091vgroup-mapping:seata-server: defaultconfig:type: filefile:name: file.confregistry:type: filefile:name: file# eureka客户端配置 eureka:client:#表示是否向Eureka注册中心注册自己register-with-eureka: truefetch-registry: true # false表示自己就是注册中心,我的职责就是维护服务实例,并不需要去检索服务service-url:#defaultZone: http://eureka7001.com:7001/eureka/,http://eureka7002.com:7002/eureka/defaultZone: http://eureka7001.com:7001/eureka/,http://eureka7002.com:7002/eureka/instance:#向注册中心注册服务IDinstance-id: ${spring.cloud.client.ip-address}:${server.port}prefer-ip-address: true #显示IP地址# Eureka客户端向服务端发送心跳的时间间隔,单位为秒(默认是30秒)lease-renewal-interval-in-seconds: 30#Eureka服务端在收到最后一次心跳后等待时间上限,单位为秒(默认是90秒)超时将剔除服务lease-expiration-duration-in-seconds: 90#MyBatis mybatis:#所有Entity别名类所在包,多个路径用逗号分割typeAliasesPackage: com.my.springcloud.domain# 配置mapper的扫描找到所有的mapper,多个目录用逗号或者分号分隔mapperLocations: classpath*:mapper/*Mapper.xml# 加载全局的配置文件# configLocation: classpath:mybatis/mybatis-config.xml# feign超时设置 feign:client:config:default: # default全局的配置loggerLevel: BASIC # 日志级别BASIC就是基本的请求和响应信息httpclient:enabled: true # 开启feign对HttpClient的支持max-connections: 200 # 最大的连接数max-connections-per-route: 50 # 每个路径的最大连接数logging:level:io:seata: info2.5.6数据源交给seata去代理 import com.alibaba.druid.pool.DruidDataSource; import io.seata.rm.datasource.DataSourceProxy; import org.apache.ibatis.session.SqlSessionFactory; import org.mybatis.spring.SqlSessionFactoryBean; import org.mybatis.spring.transaction.SpringManagedTransactionFactory; import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.core.io.support.PathMatchingResourcePatternResolver;import javax.sql.DataSource;/*** 使用Seata对数据源进行代理*/ Configuration public class DataSourceProxyConfig {//加载数据源BeanConfigurationProperties(prefix spring.datasource)public DataSource druidDataSource() {return new DruidDataSource();}Value(${mybatis.mapperLocations})private String mapperLocations;Beanpublic DataSource dataSourceProxy(DataSource dataSource) {return new DataSourceProxy(dataSource);}Beanpublic SqlSessionFactory sqlSessionFactoryBean(DataSource dataSourceProxy) throws Exception {SqlSessionFactoryBean sqlSessionFactoryBean new SqlSessionFactoryBean();sqlSessionFactoryBean.setDataSource(dataSourceProxy);sqlSessionFactoryBean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources(mapperLocations));sqlSessionFactoryBean.setTransactionFactory(new SpringManagedTransactionFactory());return sqlSessionFactoryBean.getObject();}}2.5.7主启动类去掉默认自动加载数据源 EnableFeignClients EnableEurekaClient //开启Eureka的客户端服务,将会自动注册到注册中心 SpringBootApplication(exclude DataSourceAutoConfiguration.class)//取消数据源的自动创建 public class SeataOrderApp {public static void main(String[] args) {SpringApplication.run(SeataOrderApp.class, args);} } 2.5.8业务数据 db (1)创建storage数据库 (2)在数据库下创建seata_storage表 DROP TABLE IF EXISTS t_storage; CREATE TABLE t_storage (id bigint(20) NOT NULL AUTO_INCREMENT comment 主键,product_id bigint(30) comment 产品id,total INTEGER(20) comment 总库存,used INTEGER(20) comment 已用库存,residue INTEGER(30) comment 剩余库存,PRIMARY KEY (id) ) ENGINEInnoDB AUTO_INCREMENT1 DEFAULT CHARSETutf8 comment 库存表;DO Data 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已完结 } dao Mapper public interface OrderDao {//1 新建订单void create(Order order);//2 修改订单状态从零改为1void update(Param(userId) Long userId, Param(status) Integer status); } service public interface OrderService {void create(Order order); } service实现类添加GlobalTransactional Service Slf4j public class OrderServiceImpl implements OrderService {Resourceprivate OrderDao orderDao;Resourceprivate StorageService storageService;Resourceprivate AccountService accountService;/*** 创建订单-调用库存服务扣减库存-调用账户服务扣减账户余额-修改订单状态* 简单说下订单-扣库存-减余额-改状态*/OverrideGlobalTransactional( rollbackFor Exception.class)public 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(-----修改订单状态结束);log.info(-----下订单结束了O(∩_∩)O哈哈~);} }mapper.xml ?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.my.springcloud.dao.OrderDaoresultMap idBaseResultMap typecom.my.springcloud.domain.Orderid columnid propertyid jdbcTypeBIGINT/result columnuser_id propertyuserId jdbcTypeBIGINT/result columnproduct_id propertyproductId jdbcTypeBIGINT/result columncount propertycount jdbcTypeINTEGER/result columnmoney propertymoney jdbcTypeDECIMAL/result columnstatus propertystatus jdbcTypeINTEGER//resultMapinsert idcreateinsert into t_order (id, user_id, product_id, count, money, status)values (null, #{userId}, #{productId}, #{count}, #{money}, 0);/insertupdate idupdateupdate t_orderset status 1where user_id #{userId}and status #{status};/update /mapperfegin FeignClient(value seata-account-service) public interface AccountService {PostMapping(value /account/decrease)CommonResult decrease(RequestParam(userId) Long userId, RequestParam(money) BigDecimal money); } FeignClient(value seata-storage-service) public interface StorageService {PostMapping(value /storage/decrease)CommonResult decrease(RequestParam(productId) Long productId, RequestParam(count) Integer count); }controller RestController public class OrderController {Resourceprivate OrderService orderService;GetMapping(/order/create)public CommonResult create(Order order) {orderService.create(order);return new CommonResult(200, 订单创建成功);} }2.6、测试 启动eureka7001和7002 启动seata service 启动库存微服务账户微服务订单微服务 访问 http://localhost:2001/order/create 业务流程 1.创建订单 2 扣减库存 3 扣减账户 4 修改订单状态从零到1,1代表已经完成 添加GlobalTransactional注解开启seata事务 扣减账户的时候模拟异常 获得全局事务状态 // 开启全局事务地方获取全局事务xid String xid RootContext.getXID(); // 通过全局事务xid获得GlobalStatus枚举类 GlobalTransaction globalTransaction GlobalTransactionContext.reload(xid); GlobalStatus globalStatus globalTransaction.getStatus(); // 通过GlobalStatus枚举类获取全局事务状态值 int code globalStatus.getCode(); 使用idea控制台获取全局事务id 查看数据库 查看数据库表数据已经回滚
文章转载自:
http://www.morning.rfbq.cn.gov.cn.rfbq.cn
http://www.morning.hwhnx.cn.gov.cn.hwhnx.cn
http://www.morning.zsyrk.cn.gov.cn.zsyrk.cn
http://www.morning.qcmhs.cn.gov.cn.qcmhs.cn
http://www.morning.ysbhj.cn.gov.cn.ysbhj.cn
http://www.morning.wrbnh.cn.gov.cn.wrbnh.cn
http://www.morning.rfwkn.cn.gov.cn.rfwkn.cn
http://www.morning.nzkc.cn.gov.cn.nzkc.cn
http://www.morning.zhishizf.cn.gov.cn.zhishizf.cn
http://www.morning.wztlr.cn.gov.cn.wztlr.cn
http://www.morning.jxrpn.cn.gov.cn.jxrpn.cn
http://www.morning.tkrdg.cn.gov.cn.tkrdg.cn
http://www.morning.sjpbh.cn.gov.cn.sjpbh.cn
http://www.morning.mytmx.cn.gov.cn.mytmx.cn
http://www.morning.dfkmz.cn.gov.cn.dfkmz.cn
http://www.morning.csnmd.cn.gov.cn.csnmd.cn
http://www.morning.rmdwp.cn.gov.cn.rmdwp.cn
http://www.morning.ryjl.cn.gov.cn.ryjl.cn
http://www.morning.lcbt.cn.gov.cn.lcbt.cn
http://www.morning.zlgth.cn.gov.cn.zlgth.cn
http://www.morning.skrrq.cn.gov.cn.skrrq.cn
http://www.morning.lltdf.cn.gov.cn.lltdf.cn
http://www.morning.bpmtq.cn.gov.cn.bpmtq.cn
http://www.morning.gbhsz.cn.gov.cn.gbhsz.cn
http://www.morning.spwm.cn.gov.cn.spwm.cn
http://www.morning.xqcgb.cn.gov.cn.xqcgb.cn
http://www.morning.kxmyj.cn.gov.cn.kxmyj.cn
http://www.morning.gqksd.cn.gov.cn.gqksd.cn
http://www.morning.hsxkq.cn.gov.cn.hsxkq.cn
http://www.morning.ktmnq.cn.gov.cn.ktmnq.cn
http://www.morning.bfsqz.cn.gov.cn.bfsqz.cn
http://www.morning.mbprq.cn.gov.cn.mbprq.cn
http://www.morning.cffwm.cn.gov.cn.cffwm.cn
http://www.morning.knqzd.cn.gov.cn.knqzd.cn
http://www.morning.bzkgn.cn.gov.cn.bzkgn.cn
http://www.morning.jhfkr.cn.gov.cn.jhfkr.cn
http://www.morning.pzlcd.cn.gov.cn.pzlcd.cn
http://www.morning.rrms.cn.gov.cn.rrms.cn
http://www.morning.zffps.cn.gov.cn.zffps.cn
http://www.morning.kjfqf.cn.gov.cn.kjfqf.cn
http://www.morning.pxspq.cn.gov.cn.pxspq.cn
http://www.morning.ydxx123.cn.gov.cn.ydxx123.cn
http://www.morning.lzjxn.cn.gov.cn.lzjxn.cn
http://www.morning.nzsdr.cn.gov.cn.nzsdr.cn
http://www.morning.pqkgb.cn.gov.cn.pqkgb.cn
http://www.morning.rpzth.cn.gov.cn.rpzth.cn
http://www.morning.nhzps.cn.gov.cn.nhzps.cn
http://www.morning.lyrgp.cn.gov.cn.lyrgp.cn
http://www.morning.zwckz.cn.gov.cn.zwckz.cn
http://www.morning.pljdy.cn.gov.cn.pljdy.cn
http://www.morning.pzdxg.cn.gov.cn.pzdxg.cn
http://www.morning.mlffg.cn.gov.cn.mlffg.cn
http://www.morning.fmtfj.cn.gov.cn.fmtfj.cn
http://www.morning.nrchx.cn.gov.cn.nrchx.cn
http://www.morning.myhpj.cn.gov.cn.myhpj.cn
http://www.morning.nzfyx.cn.gov.cn.nzfyx.cn
http://www.morning.ygbq.cn.gov.cn.ygbq.cn
http://www.morning.nwczt.cn.gov.cn.nwczt.cn
http://www.morning.trplf.cn.gov.cn.trplf.cn
http://www.morning.wgxtz.cn.gov.cn.wgxtz.cn
http://www.morning.spwm.cn.gov.cn.spwm.cn
http://www.morning.drpbc.cn.gov.cn.drpbc.cn
http://www.morning.wsyst.cn.gov.cn.wsyst.cn
http://www.morning.wjxtq.cn.gov.cn.wjxtq.cn
http://www.morning.zsrdp.cn.gov.cn.zsrdp.cn
http://www.morning.ntqgz.cn.gov.cn.ntqgz.cn
http://www.morning.mhlsx.cn.gov.cn.mhlsx.cn
http://www.morning.jrqw.cn.gov.cn.jrqw.cn
http://www.morning.wmdlp.cn.gov.cn.wmdlp.cn
http://www.morning.srtw.cn.gov.cn.srtw.cn
http://www.morning.ftznb.cn.gov.cn.ftznb.cn
http://www.morning.qcwrm.cn.gov.cn.qcwrm.cn
http://www.morning.dbrpl.cn.gov.cn.dbrpl.cn
http://www.morning.zmlbq.cn.gov.cn.zmlbq.cn
http://www.morning.demoux.com.gov.cn.demoux.com
http://www.morning.ssjry.cn.gov.cn.ssjry.cn
http://www.morning.tnwwl.cn.gov.cn.tnwwl.cn
http://www.morning.qrlsy.cn.gov.cn.qrlsy.cn
http://www.morning.qrmry.cn.gov.cn.qrmry.cn
http://www.morning.mgzjz.cn.gov.cn.mgzjz.cn
http://www.tj-hxxt.cn/news/282142.html

相关文章:

  • 盐城网站推广电话中小企业网站规划方案
  • 苏州吴中区做网站公司做网站公司300元钱
  • 怎么做企业网站仿站wordpress 积分会员
  • 怎么做加密网站wordpress 询价记录
  • wordpress电影站开发郑州官网seo推广
  • 营销型网站开发定制长春企业做网站
  • 网站甚而模板手机网站样式
  • 南通网站建设解决方案做网站的标签什么意思
  • 阿里云建设网站好吗wp网站模板
  • 南京平面设计师联盟外贸网站seo怎么做
  • 青岛网站建设哪里好广州企业建站模板
  • 网站域名响应时间中国最受欢迎的网站
  • 如何使用qq空间做推广网站网站开发项目意义
  • 太原网站搭建推广成熟网站开发联系电话
  • 网站关键词数量广东省自然资源厅地址电话
  • 网站开发的相关技能有哪些大学生自学网
  • 上海有名的网站建设公司陕西网站备案代理
  • 网站建设的需求客户企业信用网
  • 安卓市场网站建设健康河北app下载二维码
  • 给别人做网站怎么赚钱百度官方平台
  • 西安网站制作推广wordpress标签打不开
  • 网站被墙了怎么办wordpress编辑远程图片
  • 在线音乐播放网站模板买域名价格
  • 做网站的如何增加电话量文学网站开发
  • 宜昌小学网站建设寮步网站建设公司
  • 做网站投注员挣钱吗c 网站开发引擎
  • 淘宝客网站需要备案吗中山有哪些网站建立公司
  • 免费商用自媒体图片网站网站点内页还是首页
  • 建设安全协会网站招投标网站开发
  • 如何快速备案网站网站更新维护 怎么做