.Net Core with 微服务 - 分布式事务 - TCC

2023-11-05 22:38

本文主要是介绍.Net Core with 微服务 - 分布式事务 - TCC,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

上一次我们讲解了分布式事务的 2PC、3PC 。那么这次我们来理一下 TCC 事务。本次还是讲解 TCC 的原理跟 .NET 其实没有关系。

TCC

  • Try 准备阶段,尝试执行业务

  • Confirm 完成业务

  • Cancel 回滚准备阶段的业务

TCC 事务其实是 2PC 的一个扩展。上一次我们说了 2PC ,在二阶段进行事务提交。因为 2PC 基本上是利用数据库的 事务能力进行 commit ,其实这里还有可能出现一种 rollback 情况。TCC 就是把 2PC 的二阶段细化了,拆分成了 Confirm 跟 Cancel 两个步骤。TCC 是 2PC 的一次进化,TCC 拆分二阶段后已经不局限于数据库事物了,它可以适用于非数据库事物的场景。因为我们的 Cancel 阶段可以进行更加复杂的回滚能力,业务补偿能力。TCC 可以认为是业务层面的2PC 。


下面我们以使用客户积分兑换房间为示例说明一下 TCC 事务。

  1. Try 为完成 TCC 事务的 Try 阶段,我们需要在房间上增加一个状态字段“是否锁定”,一旦锁定,其它订单就没有办法预定这间房间。同样我们需要在用户积分表上增加一个字段“冻结积分”,如果涉及到并发可能要单独拉一张表出来。这里简化一点就加个字段吧。
    Try阶段开始:订单服务把房间设置为锁定状态;积分服务把用户的积分减去消耗的积分同时把消耗的积分暂存在冻结字段上。

  2. Confirm 如果一阶段都提交成功了,那么所有的服务都开始进入 Confirm 阶段。订单服务把房间状态更改为“已预定”状态;积分服务把冻结的积分清0。这样整个事务都成功完成了。

  3. Cancel 如果一阶段某个服务没有 Try 成功,那么所有的服务都要进入Cancel阶段。比如订单服务锁定房源成功了,积分冻结的时候失败了,那么订单服务要进入 Cancel 阶段,把房间的的锁定状态取消,从新释放出来。如果锁定房源失败了,积分扣减成功了,那么 Cancel 阶段就要把扣减的积分给加回去。

TCC 的一些问题

异常

如果 Confirm 阶段出现异常,TCC 管理器会不断的重试这个阶段,直到成功。因为理论上认为只要 Try 是成功的,那么 Confirm 阶段一定会成功。因为所需要的资源已经在 Try 阶段冻结了。如果 Cancel 阶段出现异常,那么 TCC 管理器也会不断的重试这个阶段来解除冻结的资源。

冥等

因为 TCC 有重试机制,所以所有的接口都需要实现幂等,避免多次调用对业务数据产生错误。比如多次扣款,多次下订单等。

并发问题

因为 TCC 事务在 Try 阶段对资源是完全的提交状态,并没有像 2PC 那样使用数据库事物来对资源进行锁定,所以在并发的时候对资源的修改要格外注意。在处理业务的时候要时刻注意锁定的资源对业务造成的一影响。

允许空取消

TCC 事务在一阶段 Try 的时候失败要运行进行 Cancel 提交。这时候 Cancel 其实是不需要做任何补偿操作,我们称之为空取消。这个时候也要注意,在编写 Cancel 操作的时候要时刻注意到底有没有完成 Try 操作,如果没有完成 Try 操作则要进行空取消。

预付悬挂

TCC 按流程上来说是不会出现悬挂情况的。但是有一种特殊情况会造成资源的悬挂。按照正常流程我们的 Try 阶段总是先于 Cancel 执行的。但是由于网络拥堵的问题造成 Try 调用延迟了,TCC 管理器在一定时间没收到 Try 成功响应后会发送 Cancel 调用,这个 Cancel 就有可能在 Try 之前先被调用了。在 Cancel 执行成功后, 这个 Try 请求调用才到达服务,这个时候如果 Try 被执行成功,那么就会造成资源的悬挂。所以当编写 Try 代码的时候同意需要注意是不是已经调用过 Cancel 操作了。

总结

TCC 事务是 2PC 的一种升级。TCC 相对于 2PC 不再依赖于本地数据库事物能力,它可以使用于应用层面的事务。它把 2PC 的提交跟回滚操作明确的抽象成 Confirm 跟 Cancel 。TCC 事务在逻辑上是比较清晰的。但是 TCC 使用起来也有不方便的地方,就是它对代码入侵比较强,比较繁琐。每个业务都要强制拆分成3个方法。而且还要还要注意幂等,空取消,悬挂等问题。

相关文章

NET Core with 微服务 - 什么是微服务
.Net Core with 微服务 - 架构图
.Net Core with 微服务 - Ocelot 网关
.Net Core with 微服务 - Consul 注册中心
.Net Core with 微服务 - Seq 日志聚合
.Net Core with 微服务 - Elastic APM
.Net Core with 微服务 - Consul 配置中心
.Net Core with 微服务 - Polly 熔断降级
.Net Core with 微服务 - 分布式事务 - 2PC、3PC

关注我的公众号一起玩转技术


这篇关于.Net Core with 微服务 - 分布式事务 - TCC的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/352917

相关文章

Spring Boot 与微服务入门实战详细总结

《SpringBoot与微服务入门实战详细总结》本文讲解SpringBoot框架的核心特性如快速构建、自动配置、零XML与微服务架构的定义、演进及优缺点,涵盖开发环境准备和HelloWorld实战... 目录一、Spring Boot 核心概述二、微服务架构详解1. 微服务的定义与演进2. 微服务的优缺点三

RabbitMQ消息总线方式刷新配置服务全过程

《RabbitMQ消息总线方式刷新配置服务全过程》SpringCloudBus通过消息总线与MQ实现微服务配置统一刷新,结合GitWebhooks自动触发更新,避免手动重启,提升效率与可靠性,适用于配... 目录前言介绍环境准备代码示例测试验证总结前言介绍在微服务架构中,为了更方便的向微服务实例广播消息,

Jenkins分布式集群配置方式

《Jenkins分布式集群配置方式》:本文主要介绍Jenkins分布式集群配置方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录1.安装jenkins2.配置集群总结Jenkins是一个开源项目,它提供了一个容易使用的持续集成系统,并且提供了大量的plugin满

关于DNS域名解析服务

《关于DNS域名解析服务》:本文主要介绍关于DNS域名解析服务,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录DNS系统的作用及类型DNS使用的协议及端口号DNS系统的分布式数据结构DNS的分布式互联网解析库域名体系结构两种查询方式DNS服务器类型统计构建DNS域

Spring事务传播机制最佳实践

《Spring事务传播机制最佳实践》Spring的事务传播机制为我们提供了优雅的解决方案,本文将带您深入理解这一机制,掌握不同场景下的最佳实践,感兴趣的朋友一起看看吧... 目录1. 什么是事务传播行为2. Spring支持的七种事务传播行为2.1 REQUIRED(默认)2.2 SUPPORTS2

Linux中SSH服务配置的全面指南

《Linux中SSH服务配置的全面指南》作为网络安全工程师,SSH(SecureShell)服务的安全配置是我们日常工作中不可忽视的重要环节,本文将从基础配置到高级安全加固,全面解析SSH服务的各项参... 目录概述基础配置详解端口与监听设置主机密钥配置认证机制强化禁用密码认证禁止root直接登录实现双因素

java向微信服务号发送消息的完整步骤实例

《java向微信服务号发送消息的完整步骤实例》:本文主要介绍java向微信服务号发送消息的相关资料,包括申请测试号获取appID/appsecret、关注公众号获取openID、配置消息模板及代码... 目录步骤1. 申请测试系统2. 公众号账号信息3. 关注测试号二维码4. 消息模板接口5. Java测试

解决未解析的依赖项:‘net.sf.json-lib:json-lib:jar:2.4‘问题

《解决未解析的依赖项:‘net.sf.json-lib:json-lib:jar:2.4‘问题》:本文主要介绍解决未解析的依赖项:‘net.sf.json-lib:json-lib:jar:2.4... 目录未解析的依赖项:‘net.sf.json-lib:json-lib:jar:2.4‘打开pom.XM

javax.net.ssl.SSLHandshakeException:异常原因及解决方案

《javax.net.ssl.SSLHandshakeException:异常原因及解决方案》javax.net.ssl.SSLHandshakeException是一个SSL握手异常,通常在建立SS... 目录报错原因在程序中绕过服务器的安全验证注意点最后多说一句报错原因一般出现这种问题是因为目标服务器

SpringBoot服务获取Pod当前IP的两种方案

《SpringBoot服务获取Pod当前IP的两种方案》在Kubernetes集群中,SpringBoot服务获取Pod当前IP的方案主要有两种,通过环境变量注入或通过Java代码动态获取网络接口IP... 目录方案一:通过 Kubernetes Downward API 注入环境变量原理步骤方案二:通过