分布式与一致性协议之TCC协议

TCC协议

概述

虽然MySQL XA能实现数据层的分布式事务,解决多个MySQL操作的事务问题,但还面临别的问题:在接收到外部的指令后,需要访问多个内部系统,执行指令约定的操作,还必须保证指令执行的原子性(也就是事务要么全部成功,要么全部失败)。那么如何实现指令执行的原子性呢?答案是TCC.
在我看来,基于二阶段提交的XA规范实现的是数据层面操作的事务,而TCC能实现业务层面操作的事务。理解了二阶段提交协议和TCC后,我们就可以从数据层面到业务层面更加全面地理解如何实现分布式事务了,从而在日常工作中更清楚地知道如何处理操作地原子性或者系统状态的一致性等问题。

我们还是先来看一道思考题。
以如何实现订票系统为例,假设现在要实现一个给内部员工提供机票订购服务的企鹅订票系统,但在实现订票系统时,我们需要考虑这样的情况:我想从深圳飞北京,但没有直达的机票,要先顶深圳航空的航班从深圳去上海,再定上海航空的航班从上海去北京,如图所示。
因为我的目的地时北京,所以如果只有一张机票订购成功肯定是不行的。这个系统必须保障两个订票操作的事务要么全部成功,要么全部不成功,那么该如何实现两个订票操作的事务呢?带着这个问题,我们先来了解下什么是TCC
在这里插入图片描述

什么是TCC

前面已经在CAP理论介绍了TCC,这里只想补充一点:可以对比二阶段提交协议来理解TCC包含的预留(Try)、确认(Confirm0或撤销(Cancel)这两个阶段,分析如下。

  • 1.预留和二阶段提交协议中的提交请求阶段的操作类似,具体是指系统会将需要确认的资源预留、锁定,确保确认操作一定能执行成功。
  • 2.确认和二阶段提交协议中的提交执行阶段的操作类似,具体是指系统将最终执行的操作
  • 3.撤销比较像二阶段提交协议中的回滚操作,具体是指系统将撤销之前预留的资源,也就是撤销已执行的预留操作对系统产生的影响。

在我看来,二阶段提交协议和TCC的目标都是实现分布式事务,这也就决定了它们在思想上是类似的。但是这两种算法解决的问题场景是不同的,一个是数据层面,一个是业务层面,这就决定了它们在细节实现是不同的。所以接下来,我们就一起看看TCC的细节。
为了更好地演示TCC的原理,我们假设深圳航空、上海航空分别为订票系统提供了以下3个接口:机票预留接口、确认接口和撤销接口。那么这时,订票系统可以这样来实现操作的事务。
首先,订票系统调用两个航空公司的机票预留接口,向两个航空公司申请机票预留。如图所示。在这里插入图片描述

如果两个机票都预留成功,那么订票系统将执行确认操作,也就是订购机票,如图所示。
在这里插入图片描述

但如果此时有机票没有预留成功(比如深圳航空从深圳到上海的机票),那么该怎么办呢?这时订票系统就需要通过撤销解耦来撤销订票请求,如图所示。在这里插入图片描述

至此,我们就实现了订票操作的事务。在我看来,TCC的难点不在于理解TCC的原理,而在于如何根据实际场景特点来实现预留、确认、撤销3个操作。所以,为了更深刻地理解TCC的3个操作的实现要点,将以一个实际项目为例展开详细说明。

如何通过TCC实现指令执行的原子性

前文提到,当接收到外部指令时,需要实现操作1、2、3,如果其中任何一个操作失败,那么我都需要暂停指令执行,将系统恢复到操作未执行状态,然后重试,如图所示.在这里插入图片描述
其中,操作1、2、3的含义具体如下.

  • 1.操作1:生成指定URL页面对应的图片并持久化存储
  • 2.操作2:调用内部系统1的接口,禁用指定域名的访问权限
  • 3.操作3:通过MySQL XA更新多个数据库的数据记录。

那么我是如何通过TCC来解决这个问题的呢?答案是我在实现每个操作时都会分别实现响应的预留、确认、撤销操作.

首先,操作1是生成指定URL页面对应的图片,具体操作如下:

  • 1.预留操作:生成指定页面的图片并存储到本地
  • 2.确认操作:更新操作1状态为完成
  • 3.撤销操作:删除本地存储的图片

其次,因为操作2是调用内部系统1的解耦,禁用该域名的访问权限,具体操作如下.

  • 1.预留操作:调用内部系统1的禁用指定域名的预留接口,通知内部系统1预留相关的资源
  • 2.确认操作:调用内部系统1的禁用指定域名的确认接口,执行禁用域名的操作
  • 3.撤销操作:调用内部系统1的禁用指定域名的撤销接口,撤销对该域名的禁用,并通知内部系统1释放相关的预留资源

最后,操作3是通过MySQL XA更改多个MySQL数据库中的数据记录,并实现数据更新的事务,具体操作如下.

  • 1.预留操作:执行XA START和XA END命令准备好事务分支操作,并调用XA PREPARE执行二阶段提交协议的提交请求,预留相关资源
  • 2.确认操作:调用XA COMMIT执行确认操作
  • 3.撤销操作:调用XA ROLLBACK执行回滚操作,释放在预留阶段预留的资源.

可以看到,确认操作时预留操作的下一个操作,而撤销操作则是用来撤销一致性的预留操作对系统产生的影响,类似在复制粘贴时,我们通过"Ctrl Z"撤销"Ctrl V"操作的执行,如图所示,这是理解TCC的关键在这里插入图片描述

综上所述,我们首先执行操作1、2、3的预留曹祖,如果预留操作都执行成功了,那么我们将执行确认操作,继续向下执行。但如果预留操作只是部分执行成功,那么我们将执行撤销操作,取消预留操作对系统产生的影响。通过这种方式(指令对应的操作要么全部执行,要么全部不执行),我们就能实现指令的原子性了。
另外,在执行确认、撤销操作时,有一点需要我们尤为注意,即这两个操作在执行时可能会重试,所以它们需要支持幂等性

重点总结

  • 1.TCC是个业务层面的分布式事务协议,而XA规范是数据层面的分布式事务协议,这也是TCC和XA规范的最大区别。TCC与业务紧密耦合,在实际场景中,需要我们根据场景特点和业务逻辑设计响应的预留、确认、撤销操作。相比MySQL XA,TCC有一定的编程开发工作量。
  • 2.因为TCC是在业务代码中编码实现的,所以,TCC可以跨数据库、跨业务系统实现资源管理,满足复杂业务场景下的事务需求。比如,TCC可以将对不同的数据库、不同的业务系统的多个操作通过编码方式转换为一个原子操作,实现事务
  • 3.因为TCC的每一个操作对于数据库来讲,都是一个本地数据库事务,所以当操作结束时,本地数据库事务的执行就完成了,相关的数据库资源也就被释放了,这就避免了数据库层面的二阶段提交协议长时间锁定资源,导致系统性能低下的问题。

想必你会有这样的疑问:如果有人作恶,Raft、TCC这些算法还使用吗?答案时不适用,因为Raft、TCC算法时非拜占庭容错算法,不适用于拜占庭容错的场景,而常用的拜占庭容错算法有PBFT、PoW算法

  • 9
    点赞
  • 31
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
TCC(Try-Confirm-Cancel)是一种分布式事务解决方案,它通过将一个事务拆分成三个阶段(Try、Confirm、Cancel)来保证事务的一致性。而在分布式环境下,TCC通常使用3PC协议来实现。 3PC(Three-Phase Commit)协议是一种常用的分布式事务协议,它将一个分布式事务分为三个阶段(CanCommit、PreCommit、DoCommit),并通过协调者(Coordinator)和参与者(Participant)之间的消息交换来实现事务的原子性和一致性。 具体来说,TCC使用的3PC协议流程如下: 1. CanCommit 阶段:协调者向参与者发送CanCommit请求,询问参与者是否可以执行该事务。如果参与者可以执行,则发送Yes响应,否则发送No响应。 2. PreCommit 阶段:协调者向参与者发送PreCommit请求,告诉参与者可以执行该事务,并让它准备好提交或撤销事务。如果参与者准备好了,则发送Ack响应。 3. DoCommit 阶段:协调者向参与者发送DoCommit请求,告诉参与者提交该事务。如果参与者成功提交了事务,则发送Ack响应,否则发送Abort响应。 如果任何一个阶段出现问题,协调者会向参与者发送Cancel请求,撤销事务。 需要注意的是,在TCC中,Try阶段和Cancel阶段由应用程序自己来实现,3PC协议主要用于Confirm和DoCommit阶段的协调。此外,由于3PC协议的复杂性和性能问题,TCC并不适用于所有的分布式事务场景,开发者需要根据具体的业务需求来选择合适的解决方案。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

coffee_babe

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值