通俗易懂分布式事务之2PC、3PC、Seata AT模式、Seata TCC模式
通俗易懂分布式事务之2PC、3PC、AT、TCC
单机服务事务提交回滚操作是需要拿到Connection对象,调用提交commit方法或者rollback方法回滚的,例如下面操作
Connection conn = DriverManager.getConnection(...);
try{
con.setAutoCommit(false);
Statement stmt = con.createStatement();
//1 or more queries or updates
con.commit();
}catch(Exception e){
con.rollback();
}finally{
con.close();
}
要想提交或者回滚,必须拥有Connection对象,然而在分布式环境,jvm都是不同的,自然就拿不到其他服务的Connection对象,所以在分布式环境,我们无法保证原子性。因此分布式事务就需要另寻出路。
1. 术语
- 全局事务:分布式环境,操作涉及很多服务,全局事务能保证这些服务的原子性,要提交就全部服务都会提交,要回滚全部服务都会回滚
- 分支事务:分支事务建立在全局事务当中,是属于单个服务的事务
2. 2PC
2PC 即两阶段提交协议,是将整个事务流程分为两个阶段,准备阶段(Prepare phase)、提交阶段(commit phase)
与本地事务的区别就是 会加入一个事务协调者的角色,这个事务协调者控制整体的事务提交
2.1 流程
- PreCommit阶段
事务协调者开启全局事务,参与者向事务协调者注册分支事务,然后走自己的业务代码,在这过程中如果发生了异常参与者会发送信息到事务协调者我异常了,需要全部回滚。如果一切正常,告诉事务协调者我可以提交了,等待事务协调者发送commit指令 - Commit阶段
事务协调者向所有分支事务发送commit指令,释放数据库资源
在这里举个具体的例子
我们有两个服务:订单服务、库存服务
用户需要买东西,首先要创建订单,创建订单前需要去锁定库存,然后再去创建订单。
1. 事务协调者开启全局事务
2. 库存服务开启事务,向事务协调者注册一个分支事务
3. 库存服务锁定库存
4. 订单服务开启事务,向事务协调者注册一个分支事务
5. 订单服务创建订单
6. 事务协调者进行全局提交事务
7. 库存服务提交事务
8. 订单服务提交事务
9. 全局事务完成
在任何一个流程中异常,事务协调者都会发起全局回滚事务,这种方式,在全局事务完成前,Connection对象都不会释放,因为你释放了你就无法控制了,缺点很明显,如果订单服务需要处理很久,库存服务Connection对象都不会释放,一直占用着,这种是强原子性的很浪费资源
2.2 实现2PC
XA协议,是X/Open组织提出的跨异构技术实现2PC的接口标准。
使用XA协议首先前提就是,需要关系型数据库支持,目前主流数据库:
- MySQL: InnoDB 引擎支持 XA 事务,并实现了 XA 接口。
- PostgreSQL: 从版本 8.0 开始支持 XA 事务,通过插件接口实现。
- Oracle: 支持 XA 事务,使用 OracleXADataSource 提供 XA 接口。
- SQL Server: 支持 XA 事务,使用 MSDTC 提供 XA 接口。
- DB2: 支持 XA 事务,使用 DB2 Universal JDBC 驱动器提供 XA 接口。
- Sybase ASE: 支持 XA 事务,使用 JConnect 提供 XA 接口。
2.2.1 MySQL实现流程:
- START
第一步开启XA事务
库存DB:
XA START 'xid'
UPDATE product SET num = num - 1 where id = 100
XA END 'xid'
订单DB:
XA START 'xid'
INSERT INTO order values(xxx)
XA END 'xid'
- PREPARE
第二步,准备就绪,等待事务协调者同意我提交
库存DB:
XA PREPARE 'xid'
订单DB:
XA PREPARE 'xid'
- commit
全部提交
库存DB
XA COMMIT 'xid'
订单DB:
XA COMMIT 'xid'
2.2.3 seata支持XA
XA协议JDK接口定义:javax.sql.XADataSource
seata框架支持XA协议,seataXA模式文档:https://seata.apache.org/zh-cn/docs/v1.6/dev/mode/xa-mode/
seata官方XA模式demo:
https://github.com/apache/incubator-seata-samples/tree/master/xa-sample/springboot-feign-seata-xa
2.3 2PC缺陷
- 强一致性,每个分支事务得等待所有分支事务都准备好,才能提交释放
- 协调者发生故障。分支事务会一直阻塞下去。
2. 3PC
三阶段提交协议(3PC)主要是为了解决两阶段提交协议的阻塞问题,2pc存在的问题是当协作者崩溃时,参与者一直阻塞。
与两阶段提交不同的是
- 引入超时机制
- 在最前面引入CanCommit阶段,为了防止参与者服务不可用,询问各个服务能不能开启事务
2.1 流程:
- CanCommit阶段
事务询问阶段,协调者向参与者发送CanCommit请求,询问是否可以执行事务提交操作。如果有参与者返回NO,就不进行下一步操作了 - PreCommit阶段
进入PreCommit后就和2PC一样了,区别就是有超时机制 - Commit阶段
提交,释放数据库资源,与2PC一样
2.2 缺点
还是要等到全局事务完毕资源才释放,占用资源大
3. Seata AT模式
Seata AT模式文档:https://seata.apache.org/zh-cn/docs/v1.6/dev/mode/at-mode
Seata AT模式的核心是对业务无侵入,是一种改进后的2PC
主要的实现是,在每个服务的数据库中新建一张undo_log表,结构如下:
content: 更改后的内容,
rollback_info: 回滚的内容
每个分支事务执行SQL都会解析SQL,保存content,rollback_info,插入到undo_log表中。如果全局事务通知需要回滚,去通过对比content和解析rollback_info,执行sql达到回滚的效果,如果全局事务通知全局事务成功,异步删除undo_log的记录。
这种方式不需要等待全局事务的提交才提交,能解决2PC、3PC资源占用的问题,实际就是异常就去补偿的思想
3.1 流程
- 事务入口会开启全局事务,分支事务注册事务(非入口事务通过传递xid来判断是加入哪个事务)
- 分支事务执行SQL之前会解析SQL,生成前置镜像
- 解析出SQL如果是更新修改数据这种情况,seata会锁住更新修改的数据,另一个全局事务进来想要更改更新修改的数据就需要等待全局事务结束才能进行更改对应着seata的lock_table表
- 执行SQL
- 根据SQL生成后置镜像,如果到时候需要回滚,直接执行后置镜像
- 插入数据到undo_log表
- 提交本地事务
- 如果所有分支事务都是正常的,就释放锁,然后异步删除所有的分支事务undo_log的记录
- 如果发生异常,所有事务都对前置镜像进行解析,生成SQL,执行回滚操作
- 如果发生异常,需要回滚,后置镜像当中的值,不等于当前值,代表有其他业务一样的更改了这行数据,这时候就需要人工去处理了(往往如果设置了数据库字段update_time自动更新时间会很容易导致这个情况出现,不能用数据库的自动更新时间,自动更新时间得去到业务代码实现里)
3.2 缺点
seata AT模式,事务是软状态需要考虑数据最终一致性,性能相对来说不是那么高,得去加锁,得动态去解析SQL插入数据库增加了和数据库的交互
4. Seata TCC模式
Seata TCC模式文档:https://seata.apache.org/zh-cn/docs/v1.6/dev/mode/tcc-mode
TCC 是分布式事务中的二阶段提交协议,它的全称为 Try-Confirm-Cancel,即资源预留(Try)、确认操作(Confirm)、取消操作(Cancel),TCC模式对代码的入侵很大,但它的性能很好,还可以便捷的解决、空回滚、幂等、悬挂问题。
空回滚:没有执行try却执行了cancel。参与者分支注册完成之后会执行参与者一阶段try RPC 方法发送rpc时候网络延迟抖动,事务协调者全局回滚,参与者没有执行try却进入cancel
幂等:多次进入try。执行完二阶段之后,由于网络抖动或者宕机问题,会造成事务协调者收不到参与者执行confirm的返回结果,事务协调者会重复发起调用,直到二阶段执行结果成功
悬挂:执行了cancel又进入try。进入try 方法时,出现网路拥堵,由于 seata 全局事务有超时限制,执行 try 方法超时后,进行全局回滚,回滚完成后如果此时 RPC 请求才到达参与者 ,执行 try 方法进行资源预留,从而造成悬挂。
Seata社区这个博客写的挺好 https://seata.apache.org/zh-cn/blog/seata-tcc/ 解释了seata是怎么样处理解决、空回滚、幂等、悬挂问题。
4.1 流程
假设一个转账需求,A给B转100,一般做法是判断够不够钱,如果够钱A-100,B+100
在TCC模式下把这个需求拆分为 Try-Confirm-Cancel
- try 阶段,查询A够不够钱,够的话冻结A 100块钱
- confirm阶段,执行业务代码,预先给B + 100
- 如果一切正常,执行A-100,B + 100
- 如果有异常,执行try的回滚逻辑,A解除冻结的100
4.2 缺点
TCC模式有代码侵入,需要把一个业务拆分为三个方法,事务具有软状态,确认和取消操作都可能出现问题,需要考虑如何处理失败情况以保证最终一致性
通俗易懂分布式事务之2PC、3PC、Seata AT模式、Seata TCC模式的更多相关文章
- 分布式事务(1)---2PC和3PC理论
分布式事务(1)---2PC和3PC理论 分布式事物基本理论:基本遵循CPA理论,采用柔性事物特征,软状态或者最终一致性特点保证分布式事物一致性问题. 分布式事物常见解决方案: 2PC两段提交协议 3 ...
- 分布式事务与Seate框架(3)——Seata的AT模式实现原理
前言 在上两篇博文(分布式事务与Seate框架(1)--分布式事务理论.分布式事务与Seate框架(2)--Seata实践)中已经介绍并实践过Seata AT模式,这里一些例子与概念来自这两篇(特别是 ...
- 分布式事务的2PC、3PC和TCC
1.2PC协议 2PC 是二阶段提交(Two-phase Commit)的缩写,顾名思义,这个协议分两阶段完成.第一个阶段是准备阶段,第二个阶段是提交阶段,准备阶段和提交阶段都是由事务管理器(协调者) ...
- 面试被问分布式事务(2PC、3PC、TCC),这样解释没毛病!
整理了一些Java方面的架构.面试资料(微服务.集群.分布式.中间件等),有需要的小伙伴可以关注公众号[程序员内点事],无套路自行领取 更多优选 一口气说出 9种 分布式ID生成方式,面试官有点懵了 ...
- 分布式事务一2PC
分布式事务解决方案之2PC(两阶段提交) 前面已经学习了分布式事务的基础理论,以理论为基础,针对不同的分布式场景业界常见的解决方案有2PC.TCC.可靠消息最终一致性.最大努力通知这几种. 3.1.什 ...
- 分布式事务概述--2pc的概念
转载自一个大拿:http://www.cnblogs.com/LBSer/p/4715395.html 前阵子从支付宝转账1万块钱到余额宝,这是日常生活的一件普通小事,但作为互联网研发人员的职业病,我 ...
- 分布式事务与Seate框架(2)——Seata实践
前言 在上一篇博文(分布式事务与Seate框架(1)--分布式事务理论)中了解了足够的分布式事务的理论知识后,到了实践部分,在工作中虽然用到了Seata,但是自己却并没有完全实践过,所以自己私下花点时 ...
- 分布式一致性算法 2PC 3PC Paxos
分布式一致性算法的目的是为了解决分布式系统 一致性算法可以通过共享内存(需要锁)或者消息传递实现,本文讨论后者实现的一致性算法,不仅仅是分布式系统中,凡是多个过程需要达成某种一致的场合都可以使用. 本 ...
- 分布式事务之深入理解什么是2PC、3PC及TCC协议?
导读 在上一篇文章<[分布式事务]基于RocketMQ搭建生产级消息集群?>中给大家介绍了基于RocketMQ如何搭建生产级消息集群.因为本系列文章最终的目的是介绍基于RocketMQ的事 ...
- 分布式事务解决方案汇总:2PC、3PC、消息中间件、TCC、状态机+重试+幂等(转)
数据一致性问题非常多样,下面举一些常见例子.比如在更新数据的时候,先更新了数据库,后更新了缓存,一旦缓存更新失败,此时数据库和缓存数据会不一致.反过来,如果先更新缓存,再更新数据库,一旦缓存更新成功, ...
随机推荐
- TNN编译及使用
要使用 CMake 和 TNN 库基于 C++ 实现神经网络模型的推理预测,你需要按照以下步骤进行操作: 准备环境 确保已安装 CMake 和 C++ 编译器.并从 TNN 的 GitHub 仓库下载 ...
- 人类讨厌AI的缺点,其实自己也有,是时候反思了。
马特·科拉默摄于Unsplash 前言:人类讨厌AI,其实就是讨厌自己! 如果你问一些人对人工智能的看法,你可能会听到诸如不道德.偏见.不准确甚至操纵这样的词语. 人工智能因为种种原因正备受批评.它让 ...
- Index - 此处的诗
虚构往事 正篇 嗯--本来发过两篇,但深愧于仓促的处理和并未完善的细节设定,隐藏了. 大概会是一个中篇的科幻故事,世界设定已经完善了(Shaya 可以作证!),但近期可能没有精力动笔. 番外 ...
- 芯片半导体基础(二) :20世纪最伟大的发明,PN结与晶体二极管
liwen01 2025.01.12 前言 PN结 是晶体管的基础,它使得晶体管能够作为一个放大或是开关元器件.晶体管的发明不仅是一个技术上的突破,也标志着电子学的一个新时代.它极大地推动了科技和社会 ...
- Linux计划任务定时备份数据
最近有项目需要定期备份mysql数据的需求,通过linux系统的crontab计划任务实现了一个简单demo,通过mysqldump命令对mysql数据进行备份. 首先新建一个脚本文件:mysqlba ...
- 最佳产品奖,TeleDB拿下!
近日,第十三届PostgreSQL技术大会在杭州举行.本次大会以"聚焦云端创新,汇聚智慧共享"为主题,行业大咖.学术精英.技术专家和技术爱好者齐聚一堂,共同探讨数据库领域的发展趋势 ...
- Win10安装MySql步骤
1.下载 下载地址:https://dev.mysql.com/downloads/mysql/ 文件地址:https://dev.mysql.com/get/Downloads/MySQL-8.3/ ...
- iceberg调研-查询Iceberg表流程
1.查询表结构 show create table data_lake_ods.dws_service_subclazz_lesson_user_learn_stat_rt_v2 CREATE TAB ...
- Python if分支
分支语句: 1.单分支语句 1 if 条件表达式: 2 print("如果成立怎么养怎么样") 例:让用户输入年龄,如果大于18就可以去网吧偷耳机age = int(input(& ...
- CF145C Lucky Subsequence 题解
首先,我们对这个幸运数进行分析,发现: \(10^9\) 以内只有 \(1023\) 个幸运数,即 \(\sum\limits_{i=0}^92^i\) 个. 考虑对幸运数和非幸运数分类讨论. 幸运数 ...