想学做网站需要学什么,wordpress电影系统,天河岗顶棠下上社网站建设公司,建e网室内设计网官网vr全景在分布式系统设计中#xff0c;随着微服务的流行#xff0c;通常一个业务操作被拆分为多个子任务#xff0c;比如电商系统的下单和支付操作#xff0c;就涉及到了创建和更新订单、扣减账户余额、扣减库存、发送物流消息等#xff0c;那么在复杂业务开发中#xff0c;如何…在分布式系统设计中随着微服务的流行通常一个业务操作被拆分为多个子任务比如电商系统的下单和支付操作就涉及到了创建和更新订单、扣减账户余额、扣减库存、发送物流消息等那么在复杂业务开发中如何保证最终数据一致性呢
TCC 事务模型是什么
TCCTry-Confirm-Cancel的概念来源于 Pat Helland 发表的一篇名为“Life beyond Distributed Transactions:an Apostate’s Opinion”的论文。
TCC 提出了一种新的事务模型基于业务层面的事务定义锁粒度完全由业务自己控制目的是解决复杂业务中跨表跨库等大颗粒度资源锁定的问题。TCC 把事务运行过程分成 Try、Confirm / Cancel 两个阶段每个阶段的逻辑由业务代码控制避免了长事务可以获取更高的性能。
TCC 的各个阶段
TCC 的具体流程如下图所示 Try 阶段调用 Try 接口尝试执行业务完成所有业务检查预留业务资源。
Confirm 或 Cancel 阶段两者是互斥的只能进入其中一个并且都满足幂等性允许失败重试。
Confirm 操作对业务系统做确认提交确认执行业务操作不做其他业务检查只使用 Try 阶段预留的业务资源。Cancel 操作在业务执行错误需要回滚的状态下执行业务取消释放预留资源。
Try 阶段失败可以 Cancel如果 Confirm 和 Cancel 阶段失败了怎么办
TCC 中会添加事务日志如果 Confirm 或者 Cancel 阶段出错则会进行重试所以这两个阶段需要支持幂等如果重试失败则需要人工介入进行恢复和处理等。
应用 TCC 的优缺点
实际开发中TCC 的本质是把数据库的二阶段提交上升到微服务来实现从而避免数据库二阶段中长事务引起的低性能风险。
所以说TCC 解决了跨服务的业务操作原子性问题比如下订单减库存多渠道组合支付等场景通过 TCC 对业务进行拆解可以让应用自己定义数据库操作的粒度可以降低锁冲突提高系统的业务吞吐量。
TCC 的不足主要体现在对微服务的侵入性强TCC 需要对业务系统进行改造业务逻辑的每个分支都需要实现 try、Confirm、Cancel 三个操作并且 Confirm、Cancel 必须保证幂等。
另外 TCC 的事务管理器要记录事务日志也会损耗一定的性能。
从真实业务场景分析 TCC
下面以一个电商中的支付业务来演示用户在支付以后需要进行更新订单状态、扣减账户余额、增加账户积分和扣减商品操作。
在实际业务中为了防止超卖有下单减库存和付款减库存的区别支付除了账户余额还有各种第三方支付等这里我们为了描述方便统一使用扣款减库存扣款来源是用户账户余额。 业务逻辑拆解
我们把订单业务拆解为以下几个步骤
订单更新为支付完成状态扣减用户账户余额增加用户账户积分扣减当前商品的库存
如果不使用事务上面的几个步骤都可能出现失败最终会造成大量的数据不一致比如订单状态更新失败扣款却成功了或者扣款失败库存却扣减了等情况这个在业务上是不能接受的会出现大量的客诉。
如果直接应用事务不使用分布式事务比如在代码中添加 Spring 的声明式事务 Transactional 注解这样做实际上是在事务中嵌套了远程服务调用一旦服务调用出现超时事务无法提交就会导致数据库连接被占用出现大量的阻塞和失败会导致服务宕机。另一方面如果没有定义额外的回滚操作比如遇到异常非 DB 的服务调用失败时则无法正确执行回滚。
业务系统改造
下面应用 TCC 事务需要对业务代码改造抽象 Try、Confirm 和 Cancel 阶段。
Try 操作
Try 操作一般都是锁定某个资源设置一个预备的状态冻结部分数据。比如订单服务添加一个预备状态修改为 UPDATING也就是更新中的意思冻结当前订单的操作而不是直接修改为支付成功。
库存服务设置冻结库存可以扩展字段也可以额外添加新的库存冻结表。积分服务和库存一样添加一个预增加积分比如本次订单积分是 100添加一个额外的存储表示等待增加的积分账户余额服务等也是一样的操作。
Confirm 操作
Confirm 操作就是把前边的 Try 操作锁定的资源提交类比数据库事务中的 Commit 操作。在支付的场景中包括订单状态从准备中更新为支付成功库存数据扣减冻结库存积分数据增加预增加积分。
Cancel 操作
Cancel 操作执行的是业务上的回滚处理类比数据库事务中的 Rollback 操作。首先订单服务撤销预备状态还原为待支付状态或者已取消状态库存服务删除冻结库存添加到可销售库存中积分服务也是一样将预增加积分扣减掉。
执行业务操作
下面来分析业务的实际执行操作首先业务请求过来开始执行 Try 操作如果 TCC 分布式事务框架感知到各个服务的 Try 阶段都成功了以后就会执行各个服务的 Confirm 逻辑。
如果 Try 阶段有操作不能正确执行比如订单失效、库存不足等就会执行 Cancel 的逻辑取消事务提交。
TCC 对比 2PC 两阶段提交
TCC 事务模型的思想类似 2PC 提交下面对比 TCC 和基于 2PC 事务 XA 规范对比。
对比 2PC 提交 第一阶段
在 XA 事务中各个 RM 准备提交各自的事务分支事实上就是准备提交资源的更新操作insert、delete、update 等而在 TCC 中是主业务操作请求各个子业务服务预留资源。
第二阶段
XA 事务根据第一阶段每个 RM 是否都 prepare 成功判断是要提交还是回滚。如果都 prepare 成功那么就 commit 每个事务分支反之则 rollback 每个事务分支。
在 TCC 中如果在第一阶段所有业务资源都预留成功那么进入 Confirm 步骤提交各个子业务服务完成实际的业务处理否则进入 Cancel 步骤取消资源预留请求。
与 2PC/XA 两阶段提交的区别
2PC/XA 是数据库或者存储资源层面的事务实现的是强一致性在两阶段提交的整个过程中一直会持有数据库的锁。TCC 关注业务层的正确提交和回滚在 Try 阶段不涉及加锁是业务层的分布式事务关注最终一致性不会一直持有各个业务资源的锁。
TCC 的核心思想是针对每个业务操作都要添加一个与其对应的确认和补偿操作同时把相关的处理从数据库转移到业务中以此实现跨数据库的事务。
TCC 分布式服务组件
在业务中引入 TCC 一般是依赖单独的 TCC 事务框架可以选择自研或者应用开源组件。TCC 框架扮演了资源管理器的角色常用的 TCC 开源组件有 Tcc-transaction、ByteTCC、Spring-cloud-rest-tcc 等。
前面介绍过的 Seata可以选择 TCC 事务模式也支持了 AT 模式及 Saga 模式。
以 Tcc-transaction 为例源码托管在 Github-tcc-transaction提供了对 Spring 和 Dubbo 的适配感兴趣的话可以查看 tcc-transaction-tutorial-sample 学习。 总结
本文介绍了 TCC 分布式事务模型的应用通过一个实际例子分析了如何应用 TCC 对业务系统进行改造并且对比了 TCC 和 2PC 两阶段提交以及 TCC 相关的开源组件。