【原创】分布式事务之TCC事务模型
引言
在上篇文章《老生常谈——利用消息队列处理分布式事务》一文中留了一个坑,今天来填坑。如下图所示
如果服务A和服务B之间是同步调用,比如服务C需要按流程调服务A和服务B,服务A和服务B要么一起成功,要么一起失败。
针对这种情况,目前业内普遍推荐使用TCC事务来解决的!
正文
ok,老规矩,我们先套一个业务场景进去,如下图所示
那页面点了支付按钮,调用支付服务,那我们后台要实现下面三个步骤
[1] 订单服务-修改订单状态
[2] 账户服务-扣减金钱
[3] 库存服务-扣减库存
达到事务的效果,要么一起成功,要么一起失败!就要采取TCC分布式事务方案!
概念
TCC的全称是(Try-Confirm-Cancel)。如下图所示
ps:TCC又可以被称为两阶段补偿事务,第一阶段try只是预留资源,第二阶段要明确的告诉服务提供者,这个资源你到底要不要,对应第二阶段的confirm/cancel,用来清除第一阶段的影响,所以叫补偿型事务。
再打个比方,说TCC太高大上是吧,讲RM中的prepare、commit、rollback接口,总知道吧。可以类比的这么理解
那差别在哪呢?
rollback、commit、prepare,站在开发者层面是感知不到的,数据库帮你做了资源的操作!
而try、confirm、cancel,站在开发者层面是能感知到的,这三个方法的业务逻辑,即对资源的操作,开发者是要自己去实现的!
好,下面套入我们的场景,怎么做呢。比如,你的订单服务中本来只有一个接口
//修改代码状态
orderClient.updateStatus();
都要拆为三个接口,即
orderClient.tryUpateStatus();
orderClient.confirmUpateStatus();
orderClient.cancelUpateStatus();
注意了:面试官如果问你,TCC有什么缺点?这就是很严重的缺点,对代码入侵性大!每套业务逻辑、都要按try(请求资源)、confirm(操作资源)、cancel(取消资源),拆分为三个接口!
具体每个阶段,每个服务业务逻辑是什么样的呢?
假设,库存数量本来是50,那么可销售库存也是50。账户余额为50,可用余额也为50。用户下单,买了1个单价为1元的商品。流程如下:
Try阶段
订单服务:修改订单的状态为支付中
账户服务:账户余额不变,可用余额减1,然后将1这个数字冻结在一个单独的字段里
库存服务:库存数量不变,可销售库存减1,然后将1这个数字冻结在一个单独的字段里
confirm阶段
订单服务:修改订单的状态为支付完成
账户服务:账户余额变为(当前值减冻结字段的值),可用余额不变(Try阶段减过了),冻结字段清0。
库存服务:库存变为(当前值减冻结字段的值),可销售库存不变(Try阶段减过了),冻结字段清0。
cancel阶段
订单服务:修改订单的状态为未支付
账户服务:账户余额不变,可用余额变为(当前值加冻结字段的值),冻结字段清0。
库存服务:库存不变,可销售库存变为(当前值加冻结字段的值),冻结字段清0。
伪代码
接下来从代码程序来说明,为了便于演示,将入参略去。
本来,你支付服务的代码是长下面这样的
那么,用上TCC模型后,代码变成下面这样
注意了,这种写法其实严格上来说,不是不行。看你业务场景,因为存在一些瑕疵,看你自己有没办法接受
(1)cancel或者confirm出现异常了,你怎么处理?
例如在cancel阶段执行如下三行代码
orderClient.cancelUpdateStatus();
accountClient.cancelDecrease();
repositoryClient.cancelDecrease();
你第二行出现异常了,第三行没跑就退出了,怎么办?你要对此进行业务补偿!
(2)大量逻辑重复
你看啊,我们的执行架构其实是这样的
try{
xxclient.try();
}catch(Throwable t){
xxclient.cancel();
throw t;
}
xxclient.confirm();
有没办法让这个架子交给框架去执行,我们告诉框架,你在每个阶段要执行哪些方法就好!
因此,需要引入TCC分布式事务框架,事务的Try、Confirm、Cancel三个状态交给框架来感知!你只要告诉框架,Try要执行啥,Confirm要执行啥,Cancel要执行啥!如果Cancel过程出现异常了,框架有内部的补偿措施给你恢复数据!
以分布式tcc框架hmily为例,如果出现cancel异常或者confirm异常的情况,在try阶段会保存好日志,Hmily有内置的调度线程池来进行恢复,不用担心。
那hmily,怎么感知状态的呢?也很简单,就是切面编程,核心逻辑如下几行
我们在使用过程中,只要通过@Tcc注解告诉框架confirm方法执行啥,cancel方法执行啥即可!其他的交给框架帮你处理!
好了,不多说了,再说下去就是hmily源码解析了,大家有空自己去了解!
挖坑
注意看,《老生常谈——利用消息队列处理分布式事务》和本文所涉及到的微服务都是同一平台的。
那如果碰到,不同平台之间调用,你要怎么保证事务?比如,我的服务要调银行接口,你觉得可能让银行接你的tcc框架么?或者让银行接你的消息对列?你们觉得现实么?当然,有的人会说:"一个http直接调了。"嗯,少年有想法!
ok,那么业内针对这种涉及到第三方接口的服务调用,如何保证一致性?大家好好思考。
【原创】分布式事务之TCC事务模型的更多相关文章
- 分布式事务之TCC事务模型
一.引言 在上篇文章<老生常谈--利用消息队列处理分布式事务>一文中留了一个坑,今天来填坑.如下图所示 如果服务A和服务B之间是同步调用,比如服务C需要按流程调服务A和服务B,服务A和服务 ...
- 分布式事务之TCC服务设计和实现注意事项
分布式事务之TCC服务设计和实现注意事项-云栖社区-阿里云 https://yq.aliyun.com/articles/609854 分布式事务之TCC事务丶一个站在Java后端设计之路的男青年个人 ...
- 转:分布式事务之TCC服务设计和实现注意事项
由公司微服务培训引起的一丢丢对TCC的好奇 原文:https://yq.aliyun.com/articles/609854 一.TCC简介 TCC是一种比较成熟的分布式事务解决方案,可用于解决跨库操 ...
- Dubbo学习系列之十五(Seata分布式事务方案TCC模式)
上篇的续集. 工具: Idea201902/JDK11/Gradle5.6.2/Mysql8.0.11/Lombok0.27/Postman7.5.0/SpringBoot2.1.9/Nacos1.1 ...
- 分布式事务Hmily TCC源码--学习整合
一.什么是分布式事务 分布式事务是指事务的参与者.支持事务的服务器.资源服务器以及事务管理器分别位于不同的分布式系统的不同节点上, 本质上来说,分布式事务是为了保证不同数据库的数据一致性 TCC事务主 ...
- 分布式事务解决方案(二)消息系统避免分布式事务 & MQ事务消息 & Sagas 事务模型
参考文档: 如何用消息系统避免分布式事务:http://blog.jobbole.com/89140/ https://www.cnblogs.com/savorboard/p/distributed ...
- 分布式事务二TCC
分布式事务解决方案之TCC 4.1.什么是TCC事务 TCC是Try.Confirm.Cancel三个词语的缩写,TCC要求每个分支事务实现三个操作:预处理Try.确认Confirm.撤销Cancel ...
- TCC事务原理
本文主要介绍TCC的原理,以及从代码的角度上分析如何实现的:不涉及具体使用示例.本文分析的是github中开源项目tcc-transaction的代码,地址为:https://github.com/c ...
- QNJR-GROUP/EasyTransaction: 依赖于Spring的一个柔性事务实现,包含 TCC事务,补偿事务,基于消息的最终一致性事务,基于消息的最大努力交付事务交付QNJR-GROUP/EasyTransaction: 依赖于Spring的一个柔性事务实现,包含 TCC事务,补偿事务,基于消息的最终一致性事务,基于消息的最大努力交付事务交付
QNJR-GROUP/EasyTransaction: 依赖于Spring的一个柔性事务实现,包含 TCC事务,补偿事务,基于消息的最终一致性事务,基于消息的最大努力交付事务交付 大规模SOA系统的分 ...
随机推荐
- 【CSS】按钮的禁用与可用 CSS Cursor 属性
禁用时的样式 可用时的样式 样式很简单,禁用就设置为灰色,可用就设置为红色,今天这个不是重点,重点的是,光标的样子 一般,禁用时候,光标移动到按钮的上方,光标如下 而在启用按钮的时候,光标移动到按钮上 ...
- Ansible 入门指南 - 安装及 Ad-Hoc 命令使用
安装及配置 ansible Ansilbe 管理员节点和远程主机节点通过 SSH 协议进行通信.所以 Ansible 配置的时候只需要保证从 Ansible 管理节点通过 SSH 能够连接到被管理的远 ...
- org.apache.maven.archiver.MavenArchiver.getManifest(org.apache.maven.project.MavenProject, org.apache.maven.archiver.MavenArchiveConfiguration)
[错误原因:]maven的配置文件不是最新的 [解决办法:]依次点击help ->Install New Software -> add ->https://otto.takari. ...
- Odd-e CSD Course Day 2
首先在第二天中其實談的更多的是在於 Test-Driven 的部分,而第一天談的偏向如何寫出一個好的 A-TDD 案例 但在第二天開始,就不太會照固定的 Topic 進行講述,而且讓團隊成員就像一個真 ...
- Dapper, 批量插入,批量更新, 以及in, like
1. 批量插入 public async Task CreateBusinessItemAsync(IEnumerable<BusinessItemsEntity> businessIte ...
- C# 操作Excel图形——绘制、读取、隐藏、删除图形
简介 本篇文章将介绍C# 如何处理Excel图形相关的问题,包括以下内容要点: 1.绘制图形 1.1 绘制图形并添加文本到图形 1.2 添加图片到图形 1.3 设置图形阴影效果 1.4 设置图形透明度 ...
- 【代码笔记】Web-CSS-CSS Float(浮动)
一, 效果图. 二,代码. <!DOCTYPE html> <html> <head> <meta charset="utf-8"> ...
- linux学习笔记-shell-script相关知识
我的邮箱地址:zytrenren@163.com欢迎大家交流学习纠错! 一.shell script的执行方法 条件:shell脚本文件必须具备可读可执行权限 1.直接命令执行 (1)使用绝对路径执行 ...
- js获取地址栏传参
地址:http://127.0.0.1:8082/prosperleedir/index.html?id=6666&name=prosper#prosper Location{ ...
- Monkey测试记录
配置环境变量,不然用不了adb命令 path这里也一样配置一下 命令的各种意思百度一下看看也就知道了 看到一篇博客推荐的一种测试命令,我也直接拿来用了 adb shell monkey -p 你的包名 ...