乐陵森森水族,做网站优化的公司的宣传海报,凡科 如何建设网站流程,企业网站的宣传功能体现在().目录 1.事务的四大特性。
2.分布式服务的事务问题。
3.seata。
3.1理论基础。
3.1.1CAP定理。
3.1.2BASE理论。
3.2初识Seata。
3.2.1Seata的架构。
3.2.2部署TC服务。
3.2.3微服务集成Seata。
3.3 seata提供的四种分布式事务解决方案。
3.3.1 XA模式。
3.3.1.1 X…目录 1.事务的四大特性。
2.分布式服务的事务问题。
3.seata。
3.1理论基础。
3.1.1CAP定理。
3.1.2BASE理论。
3.2初识Seata。
3.2.1Seata的架构。
3.2.2部署TC服务。
3.2.3微服务集成Seata。
3.3 seata提供的四种分布式事务解决方案。
3.3.1 XA模式。
3.3.1.1 XA模式原理。
3.3.1.2 实现XA模式。
3.3.2 AT模式。
3.3.2.1 AT模式原理。
3.3.2.2 AT模式的脏写问题 、AT模式的写隔离。
3.3.2.3 实现AT模式。
3.3.3 TCC模式。
3.3.3.1 TCC模式原理。 3.3.3.2 TCC模式实现。
3.3.4 SAGA模式。
3.4 seata的四种模式对比。
3.5高可用。 1.事务的四大特性。 ACID 是指数据库事务的四个特性每个字母代表一个特性 原子性Atomicity原子性要求数据库中的事务是一个不可分割的操作单元要么全部成功执行要么全部回滚不会停留在中间状态。如果一个事务中的某个操作失败那么整个事务都会被回滚到初始状态不会对数据库产生任何影响。 一致性Consistency一致性要求数据库在进行事务处理后必须保持数据的一致性状态。这意味着数据库在事务开始和结束时必须遵循预定义的规则和约束条件以确保数据的完整性和正确性。要么全部执行要么全部不执行从而保持数据的一致性要么全部成功要么全部失败 隔离性Isolation隔离性要求数据库中的每个事务都是相互隔离的即每个事务对其他事务的操作应该是不可见的以避免并发执行时的数据冲突和异常情况。数据库通过各种并发控制机制来实现隔离性如锁机制、多版本并发控制(MVCC)等。就是避免事务相互影响比如两个事务以上对相同数据同时操作或者其他事务还没成功提交就拿着用了事务在操作某些数据库记录时把其他事务隔离在这些数据库记录外事务之间不能相互影响。这样比较容易记 持久性Durability持久性要求一旦事务提交成功数据库中的数据就应该永久保存即使在系统故障或重启后也能够保持数据的一致性状态。数据库通过将数据写入稳定的存储介质如磁盘来实现持久性。 隔离性讲解如果没有隔离性可能会出现以下情况 脏读如果没有隔离性一个事务可能会读取到另一个未提交事务的数据导致读取到不正确的数据从而产生误导性的结果。我只是随便写写你居然当真了 不可重复读缺乏隔离性可能导致同一个事务内多次读取同一数据时得到不一致的结果影响事务的可靠性和一致性。前脚读完后脚就改了数据还没给用户瞧你就改了 幻读在缺乏隔离性的情况下一个事务在读取某个范围内的记录时另一个事务在该范围内插入了新的记录或删除旧的记录导致第一个事务再次读取该范围时出现了之前不存在的记录破坏了数据的一致性。趁我不注意你不是把我作业藏起来就是改成你名字你是要我怀疑人生 数据完整性问题缺乏隔离性可能导致事务之间相互干扰从而破坏了数据库中数据的完整性和一致性进而影响系统的可靠性和稳定性。你改我也改大家一起改 2.分布式服务的事务问题。 3.seata。
3.1理论基础。
3.1.1CAP定理。 C一致性出现分区问题访问独立分区节点的请求都被阻塞。 A可用性出现分区问题可以正常访问该分区节点与其他分区节点的数据不一致性。 P分区容错性在集群出现分区时整个系统也要持续对外提供服务如果不使用P相当于访问所有分区节点都被阻塞。 提醒所以P在分布式系统中是必选的A和C只能单选。 通过采用CP模型Elasticsearch保证了数据的一致性和分区容错性。当有新的文档需要写入时它会首先被写入主分片然后主分片会将变更传播给对应的副本分片。只有当主分片和副本分片都确认写入成功后写操作才会被认为是成功的从而确保了数据的一致性。 P只要是分布式服务使用了网络就有可能网络故障出现分区的情况P作用就是出现分区的情况下也能正常进行访问。 低可用性是因为当出现分区的时候部分节点与其它节点失去连接这时为了保证数据的一致性访问该部分节点的请求都会被阻塞或拒绝。如果是AP恰恰相反可以访问但是数据的一致性没了 3.1.2BASE理论。 最终一致思想不一致性、软状态分别执行和提交和最终一致的结合。 AP模式不一致性跟软状态很像 软状态 最终一致性。允许暂时不一致性 CP模式强一致性 基本可用。不允许暂时一致性 3.2初识Seata。 Seata是 2019 年 1 月份蚂蚁金服和阿里巴巴共同开源的分布式事务解决方案。致力于提供高性能和简单易用的分布 式事务服务为用户打造一站式的分布式解决方案。 官网地址http://seata.io/其中的文档、播客中提供了大量的使用说明、源码分析。 3.2.1Seata的架构。 3.2.2部署TC服务。
部署Seata的tc-server。
1.下载 首先我们要下载seata-server包地址在http://seata.io/zh-cn/blog/download.html 2.解压 在非中文目录解压缩这个zip包其目录结构如下 3.修改配置 修改conf目录下的registry.conf文件 内容如下 registry {# file 、nacos 、eureka、redis、zk、consul、etcd3、sofatype nacos # 改了,用哪个注册中心就写那个的名字然后只需要修改下面对应注册中心的参数就行nacos {application seata-tc-server # 改了serverAddr 127.0.0.1:80 # 改了group DEFAULT_GROUP # 改了namespace cluster SH # 改了SH代表上海集群的名称username nacos # 改了password nacos # 改了}eureka {serviceUrl http://localhost:8761/eurekaapplication defaultweight 1}redis {serverAddr localhost:6379db 0password cluster defaulttimeout 0}zk {cluster defaultserverAddr 127.0.0.1:2181sessionTimeout 6000connectTimeout 2000username password }consul {cluster defaultserverAddr 127.0.0.1:8500aclToken }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 nacosnacos {serverAddr 127.0.0.1:80 # 改了namespace group SEATA_GROUP username nacos # 改了password nacos # 改了dataId seataServer.properties}consul {serverAddr 127.0.0.1:8500aclToken }apollo {appId seata-server## apolloConfigService will cover apolloMetaapolloMeta http://192.168.1.204:8801apolloConfigService http://192.168.1.204:8080namespace applicationapolloAccesskeySecret cluster seata}zk {serverAddr 127.0.0.1:2181sessionTimeout 6000connectTimeout 2000username password nodePath /seata/seata.properties}etcd3 {serverAddr http://localhost:2379}file {name file.conf}
}4.在nacos添加配置 特别注意为了让tc服务的集群可以共享配置我们选择了nacos作为统一配置中心。因此服务端配置文件seataServer.properties文件需要在nacos中配好。 格式如下 配置内容如下 # 数据存储方式db代表数据库
store.modedb
store.db.datasourcedruid
store.db.dbTypemysql
store.db.driverClassNamecom.mysql.cj.jdbc.Driver
store.db.urljdbc:mysql://127.0.0.1:3306/seata?useUnicodetruerewriteBatchedStatementstrue
store.db.userroot
store.db.password123
store.db.minConn5
store.db.maxConn30
store.db.globalTableglobal_table
store.db.branchTablebranch_table
store.db.queryLimit100
store.db.lockTablelock_table
store.db.maxWait5000
# 事务、日志等配置
server.recovery.committingRetryPeriod1000
server.recovery.asynCommittingRetryPeriod1000
server.recovery.rollbackingRetryPeriod1000
server.recovery.timeoutRetryPeriod1000
server.maxCommitRetryTimeout-1
server.maxRollbackRetryTimeout-1
server.rollbackRetryTimeoutUnlockEnablefalse
server.undo.logSaveDays7
server.undo.logDeletePeriod86400000
# 客户端与服务端传输方式
transport.serializationseata
transport.compressornone
# 关闭metrics功能提高性能
metrics.enabledfalse
metrics.registryTypecompact
metrics.exporterListprometheus
metrics.exporterPrometheusPort9898 其中的数据库地址、用户名、密码都需要修改成你自己的数据库信息。 创建好如下这里有两个配置文件第一个是之前sentinel时使用的。第二个就是刚才创建的。 5.创建数据库表 特别注意tc服务在管理分布式事务时需要记录事务相关数据到数据库中你需要提前创建好这些表。 新建一个名为seata的数据库运行课前资料提供的sql文件 这些表主要记录全局事务、分支事务、全局锁信息 SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS 0;
-- ----------------------------
-- 分支事务表
-- ----------------------------
DROP TABLE IF EXISTS branch_table;
CREATE TABLE branch_table (branch_id bigint(20) NOT NULL,xid varchar(128) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,transaction_id bigint(20) NULL DEFAULT NULL,resource_group_id varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,resource_id varchar(256) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,branch_type varchar(8) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,status tinyint(4) NULL DEFAULT NULL,client_id varchar(64) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,application_data varchar(2000) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,gmt_create datetime(6) NULL DEFAULT NULL,gmt_modified datetime(6) NULL DEFAULT NULL,PRIMARY KEY (branch_id) USING BTREE,INDEX idx_xid(xid) USING BTREE
) ENGINE InnoDB CHARACTER SET utf8 COLLATE utf8_general_ci ROW_FORMAT Compact;
-- ----------------------------
-- 全局事务表
-- ----------------------------
DROP TABLE IF EXISTS global_table;
CREATE TABLE global_table (xid varchar(128) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,transaction_id bigint(20) NULL DEFAULT NULL,status tinyint(4) NOT NULL,application_id varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,transaction_service_group varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,transaction_name varchar(128) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,timeout int(11) NULL DEFAULT NULL,begin_time bigint(20) NULL DEFAULT NULL,application_data varchar(2000) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,gmt_create datetime NULL DEFAULT NULL,gmt_modified datetime NULL DEFAULT NULL,PRIMARY KEY (xid) USING BTREE,INDEX idx_gmt_modified_status(gmt_modified, status) USING BTREE,INDEX idx_transaction_id(transaction_id) USING BTREE
) ENGINE InnoDB CHARACTER SET utf8 COLLATE utf8_general_ci ROW_FORMAT Compact;
SET FOREIGN_KEY_CHECKS 1; 6.启动TC服务
启动TC服务 进入bin目录运行其中的seata-server.bat即可 打开浏览器访问nacos地址http://localhost:8848我配的端口是80默认的是8848然后进入服务列表页面可以看到seata-tc-server的信息 出现异常解决方法 解决方法是打开seata-server.bat文件添加java的jdk8路径。 找到修改前的这一行 修改后结果 然后重新启动就能成功了。 启动成功后seata-server应该已经注册到nacos注册中心了。 3.2.3微服务集成Seata。
添加seata坐标集成微服务出现报错 添加坐标后一启动服务就报错启动失败。 解决方法是添加虚拟机选项 --add-opens java.base/java.langALL-UNNAMED 微服务集成seata分布式事务 seata:registry:type: nacosnacos:server-addr: 127.0.0.1:80namespace: # 什么都不写就是publicgroup: DEFAULT_GROUPapplication: seata-tc-serverusername: nacospassword: nacostx-service-group: seata-demo # 事务组名称service:vgroup-mapping: # 事务组与cluster集群的映射关系seata-demo: SH 3.3 seata提供的四种分布式事务解决方案。 Seata提供了四种不同的分布式事务解决方案 • XA 模式强一致性分阶段事务模式牺牲了一定的可用性无业务侵入 • TCC 模式最终一致的分阶段事务模式有业务侵入 • AT 模式最终一致的分阶段事务模式无业务侵入也是 Seata 的默认模式 • SAGA 模式长事务模式有业务侵入 3.3.1 XA模式。
seata的RM也仅仅是在数据库的接口基础上做了一层简单的封装实际上seata的RM它也是调用数据库的RM实现。主流数据库基本都实现了RM。这种方法依赖数据库底层的实现如果数据库没有实现XA模式那么就用不了。
3.3.1.1 XA模式原理。 XA模式原理 XA 规范 是 X/Open 组织定义的分布式事务处理DTPDistributed Transaction Processing标准XA 规范 描述了全局的TM与局部的RM之间的接口几乎所有主流的数据库都对 XA 规范 提供了支持。 seata的XA模式 seata的XA模式做了一些调整但大体相似 RM一阶段的工作 ① 注册分支事务到 TC ② 执行分支业务 sql 但不提交 ③ 报告执行状态到 TC TC二阶段的工作 • TC 检测各分支事务执行状态 a. 如果都成功通知所有 RM 提交事务 b. 如果有失败通知所有 RM 回滚事务 RM二阶段的工作 • 接收 TC 指令提交或回滚事务 总结 XA模式的优点是什么 • 事务的强一致性满足 ACID 原则。 • 常用数据库都支持实现简单并且没有代码侵入 XA模式的缺点是什么 • 因为一阶段需要锁定数据库资源等待二阶段结束才释放性能较差 • 依赖关系型数据库实现事务 3.3.1.2 实现XA模式。 实现XA模式 Seata的starter已经完成了XA模式的自动装配实现非常简单步骤如下 1. 修改application.yml文件每个参与事务的微服务开启XA模式 seata: data-source-proxy-mode: XA # 开启数据源代理的XA模式2. 给发起全局事务的入口方法添加GlobalTransactional注解本例中是OrderServiceImpl中的create方法 Override
GlobalTransactional
public Long create(Order order) {// 创建订单orderMapper.insert(order);// 扣余额 ...略// 扣减库存 ...略return order.getId();
}3. 重启服务并测试 访问的时候出现该异常解决方法 解决方法 把数据库驱动类从8.0.27换成8.0.11就能成功启动。指定的url还要加上时区。 url: jdbc:mysql://localhost:3306/seata_demo?serverTimezoneUTC propertiesmysql.version8.0.11/mysql.version/propertiesdependencyManagementdependenciesdependencygroupIdmysql/groupIdartifactIdmysql-connector-java/artifactIdversion${mysql.version}/version/dependency/dependencies/dependencyManagement 3.3.2 AT模式。
3.3.2.1 AT模式原理。 AT模式原理 总结 简述AT模式与XA模式最大的区别是什么 • XA 模式一阶段不提交事务锁定资源 AT 模式一阶段直接提交不锁定资源。 • XA 模式依赖数据库机制实现回滚 AT 模式利用数据快照实现数据回滚。 • XA 模式强一致 AT 模式最终一致 3.3.2.2 AT模式的脏写问题 、AT模式的写隔离。 AT模式的脏写问题 AT模式的写隔离seata管理的全局事务 全局锁只对seata管理的全局事务有用非seata管理的事务不需要全局锁就能直接操作。 AT模式的写隔离非seata管理的全局事务 全局锁只对seata管理的全局事务有用非seata管理的事务不需要全局锁就能直接操作。 总结 AT模式的优点 • 一阶段完成直接提交事务释放数据库资源性能比较好 • 利用全局锁实现读写隔离 • 没有代码侵入框架自动完成回滚和提交 AT模式的缺点 • 两阶段之间属于软状态属于最终一致 • 框架的快照功能会影响性能但比 XA 模式要好很多 3.3.2.3 实现AT模式。 实现AT模式 要注意这里的两个表可能不在同一个库中。 下面是seata-at.sql文件里面的两个表注意两个表可能不在同一个库中。 -- ----------------------------
-- 这一张表是放在TC服务使用的库中在之前我们在nacos配置的TC数据库配置指定了使用seata库所以放在seata库
-- ----------------------------
DROP TABLE IF EXISTS lock_table;
CREATE TABLE lock_table (row_key varchar(128) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,xid varchar(96) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,transaction_id bigint(20) NULL DEFAULT NULL,branch_id bigint(20) NOT NULL,resource_id varchar(256) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,table_name varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,pk varchar(36) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,gmt_create datetime NULL DEFAULT NULL,gmt_modified datetime NULL DEFAULT NULL,PRIMARY KEY (row_key) USING BTREE,INDEX idx_branch_id(branch_id) USING BTREE
) ENGINE InnoDB CHARACTER SET utf8 COLLATE utf8_general_ci ROW_FORMAT Compact;-- ----------------------------
-- 这一张表是放在集成了seata的微服务的配置文件中指定了的数据库的库集成的seata的微服务我都是使用seata-demo库所以就放在这个库上。
-- ----------------------------
DROP TABLE IF EXISTS undo_log;
CREATE TABLE undo_log (branch_id bigint(20) NOT NULL COMMENT branch transaction id,xid varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT global transaction id,context varchar(128) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT undo_log context,such as serialization,rollback_info longblob NOT NULL COMMENT rollback info,log_status int(11) NOT NULL COMMENT 0:normal status,1:defense status,log_created datetime(6) NOT NULL COMMENT create datetime,log_modified datetime(6) NOT NULL COMMENT modify datetime,UNIQUE INDEX ux_undo_log(xid, branch_id) USING BTREE
) ENGINE InnoDB CHARACTER SET utf8 COLLATE utf8_general_ci COMMENT AT transaction mode undo table ROW_FORMAT Compact; 3.3.3 TCC模式。
3.3.3.1 TCC模式原理。 TCC模式原理 总结 TCC模式的每个阶段是做什么的 • Try 资源检查和预留 • Confirm 业务执行和提交 • Cancel 预留资源的释放 TCC的优点是什么 • 一阶段完成直接提交事务释放数据库资源性能好 • 相比 AT 模型无需生成快照无需使用全局锁性能最强 • 不依赖数据库事务而是依赖补偿操作可以用于非事务型数据库 TCC的缺点是什么 • 有代码侵入需要人为编写 try 、 Confirm 和 Cancel 接口太麻烦 • 软状态事务是最终一致 • 需要考虑 Confirm 和Cancel的失败情况做好幂等处理 幂等性是指无论调用多少次对系统的状态都只有一次改变。在 TCC 模式中如果参与者因为各种原因执行了多次那么整个事务的状态就会变得不确定因此需要确保每个参与者操作具有幂等性。 例如在一个转账事务中如果在“try”阶段时发生了错误导致“try”被多次调用那么在“confirm”或“cancel”阶段也可能会被多次调用。如果这些操作不具有幂等性就会出现重复的转账操作导致数据不一致。 3.3.3.2 TCC模式实现。 TCC的空回滚和业务悬挂 空回滚就是调用某分支事务的时候因为阻塞导致失败然后TC通知所有分支事务做回滚但是失败分支事务都没有执行try没有预留资源这时就需要做空回滚。如果让它执行cancel方法会执行失败然后继续尝试执行cancel。 业务悬挂已经空回滚的业务继续执行try就永远不可能confirm或cancel这就是业务悬挂。因为该全局事务已经结束了我们这时要阻止它执行。 TCC实现案例 (BusinessActionContextParameter(paramName param) 注解标记的参数会放到BusinessActionContext上下文对象中到时候通过该上下文对象可以获取该参数。 根据上面的理解分析来动手实现TCC模式 1.导入account_freeze_tbl数据库表放在微服务使用的库中。 DROP TABLE IF EXISTS account_freeze_tbl;
CREATE TABLE account_freeze_tbl (xid varchar(128) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,user_id varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,freeze_money int(11) UNSIGNED NULL DEFAULT 0,state int(1) NULL DEFAULT NULL COMMENT 事务状态0:try1:confirm2:cancel,PRIMARY KEY (xid) USING BTREE
) ENGINE InnoDB CHARACTER SET utf8 COLLATE utf8_general_ci ROW_FORMAT COMPACT; 2.定义account_freeze_tbl表的实体类。 Data
TableName(account_freeze_tbl)
public class AccountFreeze {TableId(type IdType.INPUT)private String xid;private String userId;private Integer freezeMoney;private Integer state;public static abstract class State {public final static int TRY 0;public final static int CONFIRM 1;public final static int CANCEL 2;}
} 3.定义操作account_freeze_tbl表的mybatis-plus的接口类。 Mapper
public interface AccountFreezeMapper extends BaseMapperAccountFreeze {
} 4.定义TCC两个阶段的三个接口方法。 LocalTCC
public interface AccountTCCService {TwoPhaseBusinessAction(name deduct,commitMethod fonfirm,rollbackMethod cancel)void deduct(BusinessActionContextParameter(paramName userId) String userId,BusinessActionContextParameter(paramName money) int money);boolean confirm(BusinessActionContext context);boolean cancel(BusinessActionContext context);
} 我们要做的业务操作接口 Mapper
public interface AccountMapper extends BaseMapperAccount {Update(update account_tbl set money money - ${money} where user_id #{userId})int deduct(Param(userId) String userId, Param(money) int money);Update(update account_tbl set money money ${money} where user_id #{userId})int refund(Param(userId) String userId, Param(money) int money);
} 5.实现TCC两个阶段的三个方法。 由于 confirm 和 cancel 方法的执行不会对数据进行修改因此不需要使用 Transactional 注解。这些方法通常只需要保证幂等性即可确保多次调用不会产生副作用。 Service
Slf4j
public class AccountTCCServiceImpl implements AccountTCCService {Autowiredprivate AccountMapper accountMapper;Autowiredprivate AccountFreezeMapper freezeMapper;OverrideTransactionalpublic void deduct(String userId, int money) {//0.获取全局事务idString xid RootContext.getXID();//1.判断freeze中是否有冻结记录如果有一定是cancel执行过我要拒绝业务。AccountFreeze oldFreeze freezeMapper.selectById(xid);if (oldFreeze ! null){//cancel执行过我要拒绝业务return;}//1.扣减可用余额数据库中的字段使用unsigned关键词修饰如果为负会报错然后回滚所以可以省略余额判断accountMapper.deduct(userId,money);//2.冻结金额事务状态AccountFreeze freeze new AccountFreeze();freeze.setUserId(userId);freeze.setFreezeMoney(money);freeze.setState(AccountFreeze.State.TRY);freeze.setXid(xid);freezeMapper.insert(freeze);}Overridepublic boolean confirm(BusinessActionContext context) {//1.获取事务idString xid context.getXid();//2.根据id删除冻结及记录int count freezeMapper.deleteById(xid);return count 0;}Overridepublic boolean cancel(BusinessActionContext context) {//注意这里要保留记录做空回滚和业务悬挂判断时需要用。String xid context.getXid();String userId context.getActionContext(userId).toString();//0.查询冻结记录AccountFreeze freeze freezeMapper.selectById(xid);//1.空回滚的判断判断freeze是否为null为null证明try没执行需要空回滚if (freeze null){//证明try没执行需要空回滚freeze new AccountFreeze();freeze.setUserId(userId);freeze.setFreezeMoney(0);freeze.setState(AccountFreeze.State.CANCEL);freeze.setXid(xid);freezeMapper.insert(freeze);return true;}//2.幂等判断if (freeze.getState() AccountFreeze.State.CANCEL){//已经处理过一次CANCEL了,无需重复处理return true;}//1.恢复可用余额accountMapper.refund(freeze.getUserId(),freeze.getFreezeMoney());//2.将冻结金额清零状态改为CANCELfreeze.setFreezeMoney(0);freeze.setState(AccountFreeze.State.CANCEL);int count freezeMapper.updateById(freeze);return count 1;}
} 6.修改控制类。 RestController
RequestMapping(account)
public class AccountController {Autowiredprivate AccountTCCService accountTCCService;//原本是直接使用的AccountService接口的方法PutMapping(/{userId}/{money})public ResponseEntityVoid deduct(PathVariable(userId) String userId, PathVariable(money) Integer money){accountTCCService.deduct(userId, money);return ResponseEntity.noContent().build();}
} 业务执行失败回滚后的记录。 3.3.4 SAGA模式。 3.4 seata的四种模式对比。 3.5高可用。
TC服务的高可用和异地容灾(异地容灾就是把微服务部署到不同机房。)
1.模拟异地容灾的TC集群 计划启动两台seata的tc服务节点 节点名称ip地址端口号集群名称seata127.0.0.18091SHseata2127.0.0.18092HZ 之前我们已经启动了一台seata服务端口是8091集群名为SH。 现在将seata目录复制一份起名为seata2 修改seata2/conf/registry.conf内容如下 registry {# tc服务的注册中心类这里选择nacos也可以是eureka、zookeeper等type nacos
nacos {# seata tc 服务注册到 nacos的服务名称可以自定义application seata-tc-serverserverAddr 127.0.0.1:8848group DEFAULT_GROUPnamespace cluster HZusername nacospassword nacos}
}
config {# 读取tc服务端的配置文件的方式这里是从nacos配置中心读取这样如果tc是集群可以共享配置type nacos# 配置nacos地址等信息nacos {serverAddr 127.0.0.1:8848namespace group SEATA_GROUPusername nacospassword nacosdataId seataServer.properties}
} 进入seata2/bin目录然后运行命令 seata-server.bat -p 8092 打开nacos控制台查看服务列表 点进详情查看 2.将事务组映射配置到nacos 接下来我们需要将tx-service-group与cluster的映射关系都配置到nacos配置中心。 新建一个配置 配置的内容如下 # 事务组映射关系
service.vgroupMapping.seata-demoSH
service.enableDegradefalse
service.disableGlobalTransactionfalse
# 与TC服务的通信配置
transport.typeTCP
transport.serverNIO
transport.heartbeattrue
transport.enableClientBatchSendRequestfalse
transport.threadFactory.bossThreadPrefixNettyBoss
transport.threadFactory.workerThreadPrefixNettyServerNIOWorker
transport.threadFactory.serverExecutorThreadPrefixNettyServerBizHandler
transport.threadFactory.shareBossWorkerfalse
transport.threadFactory.clientSelectorThreadPrefixNettyClientSelector
transport.threadFactory.clientSelectorThreadSize1
transport.threadFactory.clientWorkerThreadPrefixNettyClientWorkerThread
transport.threadFactory.bossThreadSize1
transport.threadFactory.workerThreadSizedefault
transport.shutdown.wait3
# RM配置
client.rm.asyncCommitBufferLimit10000
client.rm.lock.retryInterval10
client.rm.lock.retryTimes30
client.rm.lock.retryPolicyBranchRollbackOnConflicttrue
client.rm.reportRetryCount5
client.rm.tableMetaCheckEnablefalse
client.rm.tableMetaCheckerInterval60000
client.rm.sqlParserTypedruid
client.rm.reportSuccessEnablefalse
client.rm.sagaBranchRegisterEnablefalse
# TM配置
client.tm.commitRetryCount5
client.tm.rollbackRetryCount5
client.tm.defaultGlobalTransactionTimeout60000
client.tm.degradeCheckfalse
client.tm.degradeCheckAllowTimes10
client.tm.degradeCheckPeriod2000
# undo日志配置
client.undo.dataValidationtrue
client.undo.logSerializationjackson
client.undo.onlyCareUpdateColumnstrue
client.undo.logTableundo_log
client.undo.compress.enabletrue
client.undo.compress.typezip
client.undo.compress.threshold64k
client.log.exceptionRate100 3.微服务读取nacos配置 接下来需要修改每一个微服务的application.yml文件让微服务读取nacos中的client.properties文件 seata:config:type: nacos # 必须要学这个不然会报错nacos:server-addr: 127.0.0.1:8848username: nacospassword: nacosgroup: SEATA_GROUPdata-id: client.properties 重启微服务现在微服务到底是连接tc的SH集群还是tc的HZ集群都统一由nacos的client.properties来决定了。