网站建设的功能描述,建设银行网站半天进不去,做网站用的软件,铜仁公司做网站分布式事务 a.理论基础1) CAP定理2) BASE理论 b.Seata1) XA模式1.a) 实现XA模式 2) AT模式3) TCC模式3.a) 代码实现 4) Saga模式5) 四种模式对比6) TC的异地多机房容灾架构 a.理论基础
1) CAP定理
分布式系统有三个指标#xff1a;
Consistency#xff08;一致性#xff… 分布式事务 a.理论基础1) CAP定理2) BASE理论 b.Seata1) XA模式1.a) 实现XA模式 2) AT模式3) TCC模式3.a) 代码实现 4) Saga模式5) 四种模式对比6) TC的异地多机房容灾架构 a.理论基础
1) CAP定理
分布式系统有三个指标
Consistency一致性: 用户访问分布式系统中的任意节点得到的数据必须一致Availability可用性: 用户访问集群中的任意健康节点必须能得到响应而不是超时或拒绝Partition tolerance 分区容错性 Partition(分区): 因为网络故障或其它原因导致分布式系统中的部分节点与其它节点失去连接形成独立分区tolerance(容错): 在集群出现分区时整个系统也要持续对外提供服务
分布式系统无法同时满足这三个指标这个结论就叫做 CAP 定理。 2) BASE理论
BASE理论是对CAP的一种解决思路包含三个思想
Basically Available 基本可用分布式系统在出现故障时允许损失部分可用性即保证核心可用**Soft State软状态**在一定时间内允许出现中间状态比如临时的不一致状态**Eventually Consistent最终一致性**虽然无法保证强一致性但是在软状态结束后最终达到数据一致
而分布式事务最大的问题是各个子事务的一致性问题因此可以借鉴CAP定理和BASE理论
AP模式各子事务分别执行和提交允许出现结果不一致然后采用弥补措施恢复数据即可实现最终一致CP模式各个子事务执行后互相等待同时提交同时回滚达成强一致。但事务等待过程中处于弱可用状态。
b.Seata
Seata是 2019 年 1 月份蚂蚁金服和阿里巴巴共同开源的分布式事务解决方案。致力于提供高性能和简单易用的分布式事务服务为用户打造一站式的分布式解决方案。官网地址http://seata.io/其中的文档、播客中提供了大量的使用说明、源码分析。
Seata架构
Seata事务管理中有三个重要的角色
TC (Transaction Coordinator) - 事务协调者维护全局和分支事务的状态协调全局事务提交或回滚TM (Transaction Manager) - 事务管理器定义全局事务的范围、开始全局事务、提交或回滚全局事务RM (Resource Manager) - 资源管理器管理分支事务处理的资源与TC交谈以注册分支事务和报告分支事务的状态并驱动分支事务提交或回滚
Seata提供了四种不同的分布式事务解决方案
XA模式强一致性分阶段事务模式牺牲了一定的可用性无业务侵入TCC模式最终一致的分阶段事务模式有业务侵入AT模式最终一致的分阶段事务模式无业务侵入也是Seata的默认模式SAGA模式长事务模式有业务侵入
1) XA模式
XA模式原理
XA 规范 是 X/Open 组织定义的分布式事务处理DTPDistributed Transaction Processing标准XA 规范 描述了全局的TM与局部的RM之间的接口几乎所有主流的数据库都对 XA 规范 提供了支持。
seata的XA模式seata的XA模式做了一些调整但大体相似
RM一阶段的工作
1.注册分支事务到TC2.执行分支业务sql但不提交3.报告执行状态到TC
TC二阶段的工作
TC检测各分支事务执行状态 a.如果都成功通知所有RM提交事务b.如果有失败通知所有RM回滚事务
RM二阶段的工作
接收TC指令提交或回滚事务
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-1fBJtCFn-1692258967052)(C:\Users\captaindeng\AppData\Roaming\Typora\typora-user-images\image-20230816073154114.png)]
XA模式的优点是什么
事务的强一致性满足ACID原则。常用数据库都支持实现简单并且没有代码侵入
XA模式的缺点是什么
因为一阶段需要锁定数据库资源等待二阶段结束才释放性能较差依赖关系型数据库实现事务
1.a) 实现XA模式
Seata的starter已经完成了XA模式的自动装配实现非常简单步骤如下
1.修改application.yml文件每个参与事务的微服务开启XA模式
seata:data-source-proxy-mode: XA2.给发起全局事务的入口方法添加GlobalTransactional注解本例中是OrderServiceImpl中的create方法
Override
GlobalTransactional
public Long create(Order order) {// 创建订单orderMapper.insert(order);// 扣余额 ...略 // 扣减库存 ...略return order.getId();
}3.重启服务并测试
2) AT模式
AT模式原理
AT模式同样是分阶段提交的事务模型不过缺弥补了XA模型中资源锁定周期过长的缺陷。
阶段一RM的工作
1.注册分支事务2.记录undo-log数据快照3.执行业务sql并提交4.报告事务状态
阶段二提交时RM的工作
删除undo-log即可
阶段二回滚时RM的工作
根据undo-log恢复数据到更新前
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-9Jhwpq0e-1692258967053)(C:\Users\captaindeng\AppData\Roaming\Typora\typora-user-images\image-20230816083429256.png)]
AT模式与XA模式最大的区别是什么
XA模式一阶段不提交事务锁定资源AT模式一阶段直接提交不锁定资源。XA模式依赖数据库机制实现回滚AT模式利用数据快照实现数据回滚。XA模式强一致AT模式最终一致
AT模式的存在脏写问题
AT模式的优点
一阶段完成直接提交事务释放数据库资源性能比较好利用全局锁实现读写隔离没有代码侵入框架自动完成回滚和提交
AT模式的缺点
两阶段之间属于软状态属于最终一致框架的快照功能会影响性能但比XA模式要好很多
3) TCC模式
TCC模式原理
TCC模式与AT模式非常相似每阶段都是独立事务不同的是TCC通过人工编码来实现数据恢复。需要实现三个方法
Try资源的检测和预留Confirm完成资源操作业务要求 Try 成功 Confirm 一定要能成功Cancel预留资源释放可以理解为try的反向操作 TCC的优点是什么
一阶段完成直接提交事务释放数据库资源性能好相比AT模型无需生成快照无需使用全局锁性能最强不依赖数据库事务而是依赖补偿操作可以用于非事务型数据库
TCC的缺点是什么
有代码侵入需要人为编写try、Confirm和Cancel接口太麻烦软状态事务是最终一致需要考虑Confirm和Cancel的失败情况做好幂等处理
3.a) 代码实现
案例改造account-service服务利用TCC实现分布式事务
需求如下
修改account-service编写try、confirm、cancel逻辑try业务添加冻结金额扣减可用金额confirm业务删除冻结金额cancel业务删除冻结金额恢复可用金额保证confirm、cancel接口的幂等性允许空回滚拒绝业务悬挂
TCC的空回滚和业务悬挂
当某分支事务的try阶段阻塞时可能导致全局事务超时而触发二阶段的cancel操作。在未执行try操作时先执行了cancel操作这时cancel不能做回滚就是空回滚。
对于已经空回滚的业务如果以后继续执行try就永远不可能confirm或cancel这就是业务悬挂。应当阻止执行空回滚后的try操作避免悬挂 声明TCC接口
TCC的Try、Confirm、Cancel方法都需要在接口中基于注解来声明语法如下 在Account-service中的service下定义接口
LocalTCC
public interface AccountTCCService {TwoPhaseBusinessAction(name deduct, commitMethod confirm, rollbackMethod cancel)void deduct(BusinessActionContextParameter(paramName userId) String userId,BusinessActionContextParameter(paramName money) int money);boolean confirm(BusinessActionContext ctx);boolean cancel(BusinessActionContext ctx);
}在Account-service中的service的impl下实现该方法
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(userId);if (oldFreeze ! null){// CANCEL执行过要拒绝业务return;}// 1.扣减可用余额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 ctx) {// 1.获取事务idString xid ctx.getXid();// 2.根据事务id删除冻结记录int count freezeMapper.deleteById(xid);return count 1;}Overridepublic boolean cancel(BusinessActionContext ctx) {// 0.查询冻结记录String xid ctx.getXid();String userId ctx.getActionContext(userId).toString();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);}// 2.幂等判断if (freeze.getState().equals(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;}
}4) Saga模式
Saga模式是Seata提供的长事务解决方案。也分为两个阶段
一阶段直接提交本地事务二阶段成功则什么都不做失败则通过编写补偿业务来回滚
Saga模式优点
事务参与者可以基于事件驱动实现异步调用吞吐高一阶段直接提交事务无锁性能好不用编写TCC中的三个阶段实现简单
缺点
软状态持续时间不确定时效性差没有锁没有事务隔离会有脏写 5) 四种模式对比
XAATTCCSAGA一致性强一致弱一致弱一致最终一致隔离性完全隔离基于全局锁隔离基于资源预留隔离无隔离代码侵入无无有要编写三个接口有要编写状态机和补偿业务性能差好非常好非常好场景对一致性、隔离性有高要求的业务基于关系型数据库的大多数分布式事务场景都可以对性能要求较高的事务。有非关系型数据库要参与的事务。业务流程长、业务流程多参与者包含其它公司或遗留系统服务无法提供 TCC 模式要求的三个接口
6) TC的异地多机房容灾架构
TC服务作为Seata的核心服务一定要保证高可用和异地容灾。 现在将seata目录复制一份起名为seata2
1.修改seata2/conf/registry.conf内容如下
registry {# tc服务的注册中心类这里选择nacos也可以是eureka、zookeeper等type nacosnacos {# 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控制台查看服务列表
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-DnkkrX41-1692258967053)(F:\itheima\4.微服务开发框架\1.微服务开发框架\2.高级篇\day02-分布式事务\资料\assets\image-20210624151150840.png)]
点进详情查看 2.将事务组映射配置到nacos
接下来我们需要将tx-service-group与cluster的映射关系都配置到nacos配置中心。
新建一个配置 配置的内容如下
# 事务组映射关系
service.vgroupMapping.seata-demoSHservice.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.exceptionRate1003.微服务读取nacos配置
接下来需要修改每一个微服务的application.yml文件让微服务读取nacos中的client.properties文件
seata:config:type: nacosnacos:server-addr: 127.0.0.1:8848username: nacospassword: nacosgroup: SEATA_GROUPdata-id: client.properties重启微服务现在微服务到底是连接tc的SH集群还是tc的HZ集群都统一由nacos的client.properties来决定了。