美文网首页
分布式事务

分布式事务

作者: jaxtt | 来源:发表于2020-06-13 23:16 被阅读0次

    事务类型


    2PC

    2PC全称Two-phaseCommit,中文名是二阶段提交,是XA规范的实现思路,XA规范是 X/Open DTP 定义的交易中间件与数据库之间的接口规范(即接口函数),交易中间件用它来通知数据库事务的开始、结束以及提交、回滚等。XA 接口函数由数据库厂商提供。

    X/Open DTP是X/Open 组织(即现在的 Open Group )1994定义的分布式事务处理模型。XA规模型包括应用程序( AP )、事务管理器( TM )、资源管理器( RM )、通信资源管理器( CRM )四部分。一般,常见的事务管理器( TM )是交易中间件,常见的资源管理器( RM )是数据库,常见的通信资源管理器( CRM )是消息中间件。

    2PC 通常使用到XA中的三个角色TM、AP

    AP:事务发起方,通常为微服务自身;定义事务边界(事务开始、结束),并访问事务边界内的资源

    TM:事务协调方,事务操作总控;管理事务全局事务,分配事务唯一标识,监控事务的执行进度,负责事务的提交、回滚、失败恢复。

    RM:本地事务资源,根据协调方命令进行操作;管理本地共享资源(既数据库)。

    2PC流程

    2PC 分成2个阶段,第一阶段:请求阶段(commit-request phase,或称表决阶段,voting phase)和第二阶段:提交阶段(commit phase)。

    表决阶段:事务协调者(TM)串行给每个参与者(RM)发送Prepare消息,每个参与者要么直接返回失败,要么在本地SQL执行、记录事务日志(Undo、Redo),但不提交,到达一种“万事俱备,只欠东风”的状态。

    可以进一步将准备阶段分为以下三个步骤:

    1)TM串行向每个参与者节点询问是否可以执行提交操作,并等待各参与者节点的响应。

    2)参与者节点执行询问的所有SQL语句,并将Undo和Redo写入日志。

    3)各参与者节点响应TM发起的询问。如果参与者节点的事务操作实际执行成功,则返回一个”success”消息;如果参与者节点的事务操作实际执行失败,则返回一个”abort”消息。

    提交阶段:如果TM收到了参与者的失败消息或者超时,直接给每个参与者发送回滚(Rollback)消息;否则,发送提交(Commit)消息;参与者根据TM的指令执行提交或者回滚操作,释放所有事务处理过程中使用的锁资源。(注意:必须在最后阶段释放锁资源)

    分支一:当TM从所有参与者节点获得的相应消息都为”success”时:

    1)TM向所有参与者节点发出”正式提交(commit)”的请求。

    2)参与者节点正式完成操作,并释放在整个事务期间内占用的资源。

    3)参与者节点向TM发送”完成”消息。

    4)TM受到所有参与者节点反馈的”完成”消息后,完成事务。

    分支二:如果任一参与者节点在第一阶段返回的响应消息为”abort”,或者 TM在第一阶段的询问超时之前无法获取所有参与者节点的响应消息时:

    1)TM向所有参与者节点发出”回滚操作(rollback)”的请求。

    2)参与者节点利用之前写入的Undo信息执行回滚,并释放在整个事务期间内占用的资源。

    3)参与者节点向TM发送”回滚完成”消息。

    4)TM受到所有参与者节点反馈的”回滚完成”消息后,取消事务。

    第二阶段如果commit或者rollback失败了,TM负责重试直到全部执行。

    2PC存在的问题

    1、全流程的同步阻塞:不管是第一阶段还是第二阶段,所有参与节点都是事务阻塞型。当参与者占有公共资源时,其他第三方访问公共资源可能不得不处于阻塞状态。

    2、TM单点故障:由于全流程依赖TM的协调,一旦TM发生故障。参与者会一直阻塞下去。尤其在第二阶段,TM发生故障,那么所有的参与者还都处于锁定事务资源的状态中,而无法继续完成事务操作。所有参与者必须等待TM重新上线(TM重新选举)后才能继续工作。

    3、TM脑裂引起数据不一致:在第二阶段中,当TM向参与者发送commit请求之后,发生了局部网络异常或者在发送commit请求过程中TM发生了故障,这会导致只有一部分参与者接受到了commit请求。而在这部分参与者接到commit请求之后就会执行commit操作。但是其他部分未接到commit请求的机器则无法执行事务提交。于是整个分布式系统便出现了数据不一致性的现象。

    4、TM脑裂引起事务状态不确定:TM再发出commit消息之后宕机,而接收到这条消息的参与者同时也宕机了。那么即使通过选举协议产生了新的TM,这条事务的状态也是不确定的,没人知道事务是否被已经提交。

    3PC

    2PC是CP的刚性事务,追求数据强一致性。但是通过我们上面分析可以得知TM脑裂可能造成数据不一致和事务状态不确定问题。无法达到CP的完美状态。因此业界就出现了3PC,用来处理TM脑裂引起的数据不一致和事务状态不确定问题。

    因为3PC是为彻底解决的2PC的数据不一致和事务状态不确定问题而出现。根据这一个前提,加上笔者对3PC的理解,总结出3PC的注释事项:

    1)3PC确保任何分支下的数据一致性

    2)3PC确保任何分支最多3次握手得到最终结果(超时机制)

    3)RM超时后的事务状态必须从TM获取。2PC只有TM的超时机制,3PC新增了参与者(RM)的超时机制,一方面辅助解决了2PC的事务/事务问题,还能降低一定的同步阻塞问题。因为TM、RM双向超时机制,所以维基百科对3PC定义为“非阻塞”协议。

    3PC流程

    3PC 分成3个阶段:CanCommit(准备阶段)、PreCommit(对齐阶段)、DoCommit(提交阶段);

    准备阶段:跟2PC的表决阶段很类似,TM向参与者发送commit请求,参与者如果可以提交就返回Yes,否则返回No,询问超时默认参与者为No。唯一差别在于SQL层面:准备阶段只做了SQL处理,并未记录事务日志(Undo 和Redo)

    对齐阶段:TM 和 各个参与者对齐事务状态,TM 通知各个参与者事务最终状态,各个参与者如果一致未收到事务对齐通知,会在超时后从TM反查事务状态实现事务状态对齐。在SQL层面:事务状态对齐后,记录事务日志(Undo 和Redo)

    提交阶段:该阶段进行真正的事务提交。根据第二阶段得到的事务状态结果,各参与者根据TM的通知命令进行提交/abort或者超时后自动提交/abort。

    3PC只是为了解决2PC弊端的理论产物,并没有实际落地。

    TCC

    TCC 是一种补偿型事务,该模型要求应用的每个服务提供 try、confirm、cancel 三个接口,它的核心思想是通过对资源的预留(提供中间态,如账户状态、冻结金额等),尽早释放对资源的加锁,如果事务可以提交,则完成对预留资源的确认,如果事务要回滚,则释放预留的资源。

    TCC模型完全交由业务实现,每个子业务都需要实现Try-Confirm-Cancel三个接口,对业务侵入大,资源锁定交由业务方。

    1、Try:尝试执行业务,完成所有业务检查(一致性),预留必要的业务资源(准隔离性)。

    2、Confirm:确认执行业务,不再做业务检查。只使用Try阶段预留的业务资源,Confirm操作满足幂等性。

    3、Cancel:取消执行业务释放Try阶段预留业务资源。

    TCC流程

    一个完整的业务活动由一个主业务服务与若干子业务服务组成:

    1、主业务服务负责发起并完成整个业务活动

    2、业务服务提供TCC型业务操作。

    3、业务活动管理器控制业务活动的一致性,它登记业务活动中的操作,并在业务活动提交时确认所有的TCC型操作的Confirm操作,在业务活动取消时调用所有TCC型操作的Cancel操作。

    在Confirm和Cancel范围内的操作成功性需要框架来保证,只能一直重试保证资源被消耗或者释放。

    TCC和2PC对比

    TCC将事务提交划分成两个阶段,Try即为一阶段,Confirm 和 Cancel 是二阶段并行的两个分支,二选一。从阶段划分上非常像

    2PC,我们是否可以说TCC是一种2PC或者2PC变种呢?其实不可以,原因如下:

    1、2PC的操作对象在于资源层,对于开发人员无感知;而TCC的操作在于业务层,具有较高开发成本。

    2、2PC是一个整体的长事务,也是刚性事务;而TCC是一组的本地短事务,是柔性事务。

    3、2PC的Prepare(表决阶段)进行了事务准备(redolog、undolog);而TCC的Try兼备资源操作与准备能力

    4、2PC是全局锁定资源,所有参与者阻塞 交互等待TM通知;而TCC的资源锁定在于Try操作,业务方可以灵活选择业务资源的锁定粒度。

    TCC注意事项

    TCC为了解决网络不可靠引起的异常情况,要求业务方在设计上要遵循三个策略:

    1、允许空回滚:原因是异常发生在阶段一时,部分参与方没有收到 Try 请求从而触发整个事务的Cancel 操作;Try 失败或者没有执行 Try 操作的参与方收到 Cancel 请求时,要进行空回滚操作。

    2、保持幂等性:原因是异常发生在阶段二时,比如网络超时,则会重复调用参与方的 Confirm/Cancel 方法,因此Confirm/Cancel方法必须保证幂等性。

    3、防止资源悬挂:原因网络异常导致两个阶段无法保证严格的顺序执行,出现参与方侧 Try 请求比 Cancel 请求更晚到达的情况,Cancel 会执行空回滚而确保事务的正确性,但是此时 Try 方法也不可以再被执行。

    相关文章

      网友评论

          本文标题:分布式事务

          本文链接:https://www.haomeiwen.com/subject/zudtxktx.html