柔性事务和TCC

TCC事务

上一篇介绍了2PC和3PC,其主要是为了解决分布式事务中的数据一致问题。这篇就是来了解另外一种
事务的实现方式TCC以及柔性事务。

什么是柔性事务

柔性事务其实是相对传统的事务而言的。我们对传统事务称呼为刚性事务,重视强一致性。而柔性事务更在意最终一致性。

刚性事务

遵循ACID原则,重视强一致性。

柔性事务

遵循BASE理论,实现“基本可用、最终一致”。

ACID理论

ACID应该是所有开发人员最开始接触的事务原则了。ACID是Atomicity(原子性)、Consistency(一致性)、
Isolation(隔离性)、Durability(持久性)的四个首字母。其

原子性(Atomicity)

整个事务中的所有操作,要么全部完成,要么全部不完成,不可能停滞在中间某个环节。事务在执行过程中发生错误,会被回滚到事务开始前的状态,就像这个事务从来没有执行过一样。

一致性(Consistency)

一个事务可以封装状态改变(除非它是一个只读的)。事务必须保证系统始终处于一致的状态,不管在任何给定的时间里,并发事务有多少。

隔离性(Isolation)

在并发环境中,并发的事务是相互隔离的,一个事务的执行不能被其他事务干扰。
也就是说,不同的事务并发操纵相同的数据时,每个事务都有各自完整的数据空间,即一个事务内部的操作及使用的数据对其他并发事务是隔离的,并发执行的各个事务之间不能互相干扰。

持久性(Durability)

在事务完成以后,该事务对数据所作的更改便持久的保存,并不会被回滚。

BASE理论

BASE是Basically Available(基本可用),Soft state(软状态),和 Eventually consistent(最终一致性)三个短语的缩写。

Basically Available(基本可用)

基本可用指的是分布式系统在出现未知故障的时候,允许损失部分可用性来。可能是响应时间上的损失,也可能是停止部分服务。

软状态

允许系统中的数据存在中间状态,并认为该中间状态不影响系统可用性。

最终一致性

和之前硬事务的强一致性不同,此处允许系统中各个备份数据在某一时间内存在不一致的情况,但是在一段时间数据同步之后,最终需要能够达到一个一致的状态。

最终一致性

名称 描述
因果一致性 当一项业务存在顺序操作,后一项操作基于前一项的数据的时候,必须保证后一项操作的时候获得之前项的数据为最新数据,但是和此业务无关的查询则不存在限制。简单的说就是A在B操作之前,那么进行B操作的时候需要保证获得的A数据为最新,而与他们毫无相关的C则不受此影响
读己之所写 进程A更新数据后,假如这个值是最新值,那么它应该总是可以访问到的。(它不应该访问到其他副本的旧值)
会话一致性 类似上述的会话版本,某次会话时对数据的更新,此会话期间进行更新的新值,会话应该总能访问到
单调读一致性 如果进程已经看到过数据对象的某个值,那么任何后续访问都不会返回在那个值之前的值
单调写一致性 一个系统需要能够保证来自同一个进程的写操作被顺序地执行。

什么是TCC

TCC方案是可能是目前最火的一种柔性事务方案了。关于TCC(Try-Confirm-Cancel)的概念,最早是由Pat Helland于2007年发表的一篇名为《Life beyond Distributed Transactions:an Apostate’s Opinion》的论文提出。在该论文中,TCC还是以Tentative-Confirmation-Cancellation命名。正式以Try-Confirm-Cancel作为名称的是Atomikos公司,其注册了TCC商标。国内最早关于TCC的报道,应该是InfoQ上对阿里程立博士的一篇采访。经过程博士的这一次传道之后,TCC在国内逐渐被大家广为了解并接受。

根据名称我们可以知道TCC存在三个操作。try,confirm,cancel。这三个操作被分为了两个阶段分别对应:阶段一(try0),阶段二(confirm/cancel)

TCC原理

TCC被分为两个阶段,简单的说在try阶段完成业务检查同时完成资源的锁定。在confirm/cancel阶段根据第一阶段的结果进行判断是进行提交还是取消

try-尝试阶段

其主要操作有两部分

  1. 完成业务业务检查。
  2. 为事务预留足够的资源。

confirm-提交阶段

当try完成资源锁定后在confirm阶段进行业务执行。在保证事务幂等性的前提下,对预留的业务资源进行业务操作

cancel-取消

当try节点在进行业务检查或者资源锁定的时候出现异常,则进入此阶段。在保证事务幂等的前提下,对预留资源进行取消或者回滚操作。

try成功
try失败
try-检查业务执行锁定资源
try结果
confirm-使用预留的资源执行提交操作
cancel-取消任务,释放预留资源

例子

上面的介绍描述了TCC每个阶段的任务,但是没有一个具体的例子结合会让人觉得困惑。下面我就简单举个转账的例子来简单的描述下TCC逻辑

场景

现在存在三个账户 张三、李四、王五。现在张三要向李四转账10块,李四需要向王五转账10块。最终的结果应该是张三少了10元、王五多了10元。我们将此作为一个事务。

try阶段

  1. 在尝试业务阶段,首先我们需要检测执行业务的资源是否足够。上面的例子中,首先需要检测张三账户上是否足够。
  2. 检测完业务可以执行后,传统的方式我们需要直接将张三账户金额扣除10块。但是在TCC中,try阶段需要将资源设置在一个扣除和未扣除的中间态。比如用户账户数据中专门设置一个锁定金额。此时我们将张三账户中锁定10元;李四账户中锁定10元,预添加10元;王五账户中预添加十元。

confirm阶段

当try阶段完成所有的资源锁定后,可以进入confirm阶段,在此阶段事务管理器根据之前事务号找到需要执行的事务,并依次发出执行事务的请求。事务开始执行。

cancel阶段

当try阶段,进行业务检查没有通过,或是资源锁定失败的情况。在此阶段事务管理器根据之前事务号找到需要执行的事务,并根据当时事务状态取消各个业务操作。

出现异常

在TCC模式下,出现异常主要是使用日志或者队列进行重试,来保证最终一致性。假如try阶段出现异常,则会触发cancel操作。而cancel操作执行的时候发生异常,系统会使用日志或者队列中是事务信息重试cancel操作。直到事务被成功取消。假如是confirm阶段则是根据事务状态来进行重试,老保证事务完成。当然一般来说我们会有个重试次数的限制,当重试超过限制会对错误信息进行保存,后续由人工进行干涉。

TCC的优点和缺点

TCC的优点是,相比二阶段提交对资源的占用相对较少。在2PC中,在整个事务中都在对资源进行占用。这会导致性能下降。

TCC的缺点也很明显,TCC将部分事务逻辑提到业务层面。需要在业务上对资源进行变更。对于业务方面侵入性比较高,传统业务只需要一个修改接口,但使用TCC模式需要设置try、confirm、cancel三个接口。尤其对于老旧项目会有比较大的改造成本。

使用开源的TCC框架

明白了TCC的有能力的开发或公司可以搭建自己的TCC框架,但是一个稳定可靠的TCC框架需要很高的成本。所以也可以选择开源的TCC框架,比如tcc-transaction

你可能感兴趣的:(#,分布式事务,分布式)