谈谈分布式事务之二:基于DTC的分布式事务管理模型[下篇]

[续上篇] 当基于LTM或者KTM的事务提升到基于DTC的分布式事务后,DTC成为了本机所有事务型资源管理器的管理者;此外,当一个事务型操作超出了本机的范 围,出现了跨机器的调用后,本机的DTC需要于被调用者所在机器的DTC进行协助。上级对下级(包括本机DTC对本机所有资源管理器,以及上下级DTC) 的管理得前提是下级在上级那里登记,即事务登记(Transaction Enlist)。所有事务参与者,包括所有资源管理器和事务管理器(即DTC)在进行了事务等级完成之后形成了一个树形的层级结构,该结构的形成是后续的 事务提供成为可能,因此我们将其称之为事务提交树(Transaction Commit Tree)。

一、事务登记(Transaction Enlisting)和事务提交树(Transaction Commit Tree)

事务登记的目的在于建立起事务参与者(只要指资源管理器和事务管理器DTC)之间的关系,促进相互之间的协作。我们先来看看整个事务登记是如何进行的,整个事务登记流程大致如图1所示。

图1 事务登记的流程

图1所 示的事务涉及到部署与两台机器(Machine A和Machine B)上两个服务之间的交互,事务由Service初始化,在调用Service2的时候被传播到Machine B,从而将分布于两台机器的资源管理器纳入到同一个事务之中。接下来,我们对整个流程进行详细介绍。

首先,Service A开始一个新的事务,并将其最为当前执行上下文的环境事务(Ambient Transaction)。当Service A调用本机的资源管理器的时候,会将该资源管理器纳入到本事务之中(对于我们后续要介绍的System.Transactions事务,像SQL Server、Oracle以及MSMQ等资源管理器都能够自动感知到当前的环境事务)。此时,资源管理器(RM)向本机的DTC进行事务登记,从此 DTC和资源管理器之间建立起了上下级关系。

当Service A在调用Service B的时候,会将当前事务的一些信息,比如分布式事务的ID以及关于本机DTC相关信息,封装在消息中(一般是SOAP报头)向对方传递。当Service B接受到服务调用请求消息,会将事务相关的信息提取出来在本地重建事务,并将其作为当前的环境事务,该事务和原事务具有相同的ID。同时,根据得到的关于 Machine A的DTC相关信息,让本机的DTC对Machine A的DTC进行事务登记,进而使两台机器的DTC确立了上下级关系。

和Service A访问本机的资源管理器一样,Machine B的资源管理器被Service B调用并被纳入当前事务的时候,会向本机DTC进行事务登记。

当上面所述的事务登记流程结束后,参与整个分布式事务的DTC和资源管理器形成了如图2所 示的树形层次结构,由于该结构的构建主要是为了后面对整个事务的提交服务的,所以我们一般将其称为事务提交树(Transaction Commit Tree)。事务提交树的根为事务初始化服务所在机器的DTC,在整个事务提交过程中,它是总的协调者,又被称为全局提交协调器(GCC:Global Commit Coordinator )。资源管理器充当事务提交树的叶子节点,它们的父节点为本机的DTC。分布于不同机器的DTC按照事务传播的路径形成上下级关系。

图2 事务提交树

事务提交树的构建使得对分布式事务的提交成为可能,分布式事务的提交采用两阶段协议实现,接下来我们详细介绍基于两阶段提交协议的事务提交机制。

二、基于两阶段提交(2PC:Two-Phase Commit)协议的事务提交机制

不 同于基于单一资源管理器的本地事务,在一个分布式环境中时实现一个涉及到多个资源管理器的分布式事务,实现事务的ACID四大属性,要麻烦得多。当事务初 始化服务(应用或者组件,为了更佳贴近WCF,我们都称服务)完成所有相关的操作,决定提交该事务。对于分布式事务的提交,最终的结果有两个:如果所有的 操作能够顺利完成,需要持久化的数据被相应的资源管理器写入到目标资源;如果任何一个环节失败,所有持久化资源管理器将数据恢复到原来的状态。分布式事务 的整个提交过程,采用两阶段提交(2PC:Two-Phase)Commit协议完成。顾名思义,“两阶段提交”意味整个整个事务提交阶段分两个阶段,我 们现在就来详细介绍分别在这两个阶段中,都在做些什么。

注:在事务初始化服务决定提交事务之前,任何一个参与者均可以中止(Abort)该事务,任何一个参与者对事务的中止都将导致整个分布式事务的回滚。

1、第一阶段(Phase I):准备(Prepare)阶段

在 第一个阶段,作为根节点的DTC沿着事务提交树的路径,向所有事务的参与者发起请求,要求它们对本地事务的结果进行投票。被请求的参与者将本地事务结果返 回给自己的上级,对于资源管理器,自己的上级就是本机的DTC;如果自己本身就是DTC,那么自己得上级就是位于事务提交树父节点的DTC。根据具体事务 操作执行的情况,参与者投票的类型包括如下三种:

  • 就绪(Prepared):参与者同意对事务的提交,并承诺在接收到真正的提交请求后完成本地的提交任务;
  • 只读(Read-only):参与者同意对事务的提交,但是不希望接收真正的事务提交请求;
  • 中止(Aborted):参与者要求中止事务。

对 于一个非根节点DTC来说,当它从父节点接收到标准的“准备”请求后,会立即将该请求沿着事务提交树发送给自己的下级(本机的资源管理器和下级DTC), 然后根据从下级接收的所有投票结果,计算出自己投票的结果。具体的算法是:如果所有的投票结果都是“就绪”和“只读”,对应的结果是“提交”,反之,如果 任何一个投票结果是“中止”,则最终的结果就是“中止”,换句话说,任何一个事务参与者具有一票否决权最后。最后,DTC将计算出来的投票结果反馈给自己 的上级。

当根节点DTC接收到隶属于自己的所有资源管理器和下级DTC的投票结果后,采用于上面一样的算法决定整个分布式事务的最终结果。当根节点DTC决定了事务最终的结果后,整个提交过程进入第二阶段。

注:我们可以设置事务的超时时限,如果根节点DTC在该时限内没有介绍到所有参与者的投票请求,会对整个分布式事务做出回滚的决定。

2、第二阶段(Phase II):提交(Commit)或中止(Abort)

作 为事务提交树根节点的DTC根据最终的事务结果,对整个事务进行最终的提交或者中止操作。同样是沿着事务提交树的路径,提交或者中止请求被广播出去。相应 的资源管理器根据从本机DTC获得的请求,实施最终的提交或者恢复操作。当事务参与者完成了各自就的任务后,类似于第一个阶段的投票,会讲执行的结果沿着 事务提交树逆向回馈给作为根节点的DTC。

根节点DTC只有接收到所有事务参与者的基于各自事务处理的回复,才能确保整个事务被成功提交或者回滚。那么如果事务的参与者完成了第一阶段的投票,网络断开,那将如何呢?这就涉及到对未决(In-Doubt)事务的处理。

3、未决(In-Doubt)事务的处理

对 于某个分布式事务的参与者(DTC或者资源管理器)来说,在第一阶段向上级(事务提交树的父节点)投票表明提交就绪(Prepared)之后,直到它接收 到根节点DTC最终的提交或者回滚的请求,它并不知晓本地事务的结果。在这期间,如果出现当机并重启,本地的事务处于一种“未决(In-Doubt)”状 态。未决事务仅仅出现在非根节点DTC所在的机器。分布式事务采用如下的机制处理未决事务。

当重启后,对于本机的所有未决事务,DTC 会向上级DTC发送查询请求,获取每一个事务最终的结果(提交还是中止)。如果上级也不能决定事务的结果,那么请求会沿着事务提交树不断向上(沿着根的方 向)发送,直到得到一个明确的答复(不管怎样,位于根节点的全局提交协调器总是清楚事务的结果的)。

此外,当下级DTC向自己发送相同的查询请求的时候,该DTC会讲获取到的结果回复给它们。如果未决事务存在的时间太长,系统管理者可以强制提交或者中止该事务。

4、单阶段提交(SPC: Single-Phase Commit)优化

对 于事务最终结果(提交或者中止)的决策者来说,如果它具有了不止一个下级,那么采用基于投票机制的两阶段提交协议唯一选择。但是如果仅仅具有一个唯一的下 级呢,这种投票机制就没有必要了。在这种情况下,根节点DTC采用一种优化的协议来完成整个事务的提交,我们称之为单阶段提交(SPC:Single- Phase Commit)。

顾名思义,2PC意味着整个事务提交分成两个阶段,SPC则表示将其所短为一个阶段。整个流程很简单,如 果根节点DTC仅仅只有一个登记的事务参与者(本机资源管理器或者下级DTC),而不管这个下级自身具有几个下级,它不会像2PC一样先向下级发送“准 备”请求,而是直接发送提交请求,我们将这个请求成为单阶段提交(SPC)请求。接收到SPC请求的参与者,如果是资源管理器,则直接提交本地事务,并将 最终结果(成功提交或者失败中止)反馈给这个跟节点DTC。

如果SPC请求的接收者是DTC,那么会根据隶属于自己的下级的数量选择相应的提交策略。具体做法和根节点DTC提交策略的选择方式一样:如果自己具有唯一一个下级,则采用SPC,反之采用2PC。

也就是说,不仅仅是根节点DTC可以选择SPC提交事务,任何具有单一下级的DTC均可以采用SPC。但是,非根节点DTC只有在接收到SPC请求的情况下,才能选择通过SPC提交事务。如图3给 出了两颗事务提交树(图中忽略掉资源管理器,每个节点代表DTC),对于左边的树,因为根节点A和下级B均只有一个唯一的下级,所以A和B均采用 SPC,C具有两个下级,则采用2PC。而对于右边的树,因为根节点本身具有两个下级,决定了所有的节点均采用2PC,即使是对于只有一个下级的B和C。

图3 DTC对SPC和2PC的选择

我们我们介绍整个Windows平台基于DTC的分布式事务管理模型,接下来的一篇中,我将会详细介绍基于System.Transactions事务的编程。

时间: 2024-10-11 11:03:00

谈谈分布式事务之二:基于DTC的分布式事务管理模型[下篇]的相关文章

谈谈ODPS商业化(二):ODPS的计量计费模型

ODPS正式商业化以后,微博上议论比较多的是计量计费模型.刚好这件事我全程参与,仔细写写.ODPS的计量计费规则和价格请以阿里云官方网站上的说明和数字为准.这里的内容只反映当前状态,不能保证实时更新. ODPS收费以项目(Project)为单位,对存储.计算和数据下载三个方面分别计费.存储和数据下载的收费形式与其他云产品很类似.而计算这边,目前ODPS仅开放了SQL任务,计费公式为:一次SQL计算费用 = 计算输入数据量 * SQL复杂度 * SQL价格.具体而言: 1.计算输入数据量:指一个S

分布式锁(2) ----- 基于redis的分布式锁

Redis单机版实现 set和lua实现 获取锁 SET resource_name my_random_value NX PX 30000 NX key不存在时才set PX 设置过期时间 my_random_value 要保证每台客户端的每个锁请求唯一,可以使用UUID+ThreadID 该命令在Redis 2.6.12才有,网上有基于setnx.epire的实现和基于setnx.get.getset的实现,这些多多少少都有点瑕疵,大概率是旧版本的redis实现,建议高版本的redis还是使

python基于redis实现分布式锁

阅读目录 什么事分布式锁 基于redis实现分布式锁 一.什么是分布式锁 我们在开发应用的时候,如果需要对某一个共享变量进行多线程同步访问的时候,可以使用我们学到的锁进行处理,并且可以完美的运行,毫无Bug! 注意这是单机应用,后来业务发展,需要做集群,一个应用需要部署到几台机器上然后做负载均衡,大致如下图: 上图可以看到,变量A存在三个服务器内存中(这个变量A主要体现是在一个类中的一个成员变量,是一个有状态的对象),如果不加任何控制的话,变量A同时都会在分配一块内存,三个请求发过来同时对这个变

[Redis] 基于redis的分布式锁

前言分布式锁一般有三种实现方式:1. 数据库乐观锁:2. 基于Redis的分布式锁:3. 基于ZooKeeper的分布式锁.本篇博客将介绍第二种方式,基于Redis实现分布式锁. 可靠性首先,为了确保分布式锁可用,我们至少要确保锁的实现同时满足以下四个条件: 互斥性.在任意时刻,只有一个客户端能持有锁.不会发生死锁.即使有一个客户端在持有锁的期间崩溃而没有主动解锁,也能保证后续其他客户端能加锁.具有容错性.只要大部分的Redis节点正常运行,客户端就可以加锁和解锁.解铃还须系铃人.加锁和解锁必须

基于BIM技术的施工管理平台研究

BIM技术是一种数字化建模技术,它根据建筑图纸等信息生成三维的建筑模型,可以在最早期向我们展示该建筑物.BIM技术与工程项目成本管理系统相结合,方面可以提高项目前期的预算精度,同时也可以帮助企业在项目施工过程中对成本数据的精确化管理.两者相结合,BIM技术可以在整个成本管理过程中实时的对成本数据进行监管,保证其正确性. 问题 自21世纪,建筑业作为我国国民经济的支柱产业已进入高速发展期,目前正面临着大规模的基本建设.而建筑业快速发展的同时,主要存在着以下问题. 1.技术和管理水平相对落后 在激烈

谈谈分布式事务之一:SOA需要怎样的事务控制方式

在一个基于SOA架构的分布式系统体系中,服务(Service)成为了基本的功能提供单元,无论与业务流程无关的基础功能,还是具体的业务逻辑, 均实现在相应的服务之中.服务对外提供统一的接口,服务之间采用标准的通信方式进行交互,各个单一的服务精又有效的组合.编排成为一个有机的整体.在这样 一个分布式系统中某个活动(Activity)的实现往往需要跨越单个服务的边界,如何协调多个服务之间的关系使之为活动功能的实现服务,涉及到SOA一 个重要的课题:服务协作(Service Coordination).

构建基于RocketMQ的分布式事务服务

说在前面 Apache RocketMQ-4.3.0正式Release了事务消息的特性,顺着最近的这个热点.第一篇文章,就来聊一下在软件工程学上的长久的难题--分布式事务(Distributed Transaction). 这个技术也在各个诸如阿里,腾讯等大厂的内部,被广泛地实现,利用及优化.但是由于理论上就有难点,所以分布式事务就隐晦得成了大厂对于小厂的技术壁垒.相信来看这篇文章的同学,一定都听过很多关于分布式事务的术语,比较二阶段提交,TCC,最终一致性等,所以这里也不多普及概念. 基于Ro

基于Dubbo的分布式事务框架(LCN)

原文地址:http://原文地址:https://github.com/1991wangliang/transaction 该框架依赖Redis/dubbo/txManager服务.依赖第三方框架lorne_core 原理与功能 基于对spring tx PlatformTransactionManager的本地模块事务控制从而达到全局控制事务的目的.该框架兼容任何依赖PlatformTransactionManager的DB框架.利用三阶段提交的方式来确保事务的一致性,支持本地事务和分布式事务

Percolator:基于BigTable的分布式事务实现

Google为了解决网页索引的增量处理,以及维护数据表和索引表的一致性问题,基于BigTable实现了一个支持分布式事务的存储系统.这里重点讨论这个系统的分布式事务实现,不讨论percolator中为了支持增量计算而实现的Notifications机制. 该系统基于BigTable,支持snapshot isolation隔离级别,这个隔离级别不在ANSI定义的隔离级别范围内.简单来说,就是一个事务看到的是一个stable的数据库的快照.快照隔离相对于可串行化隔离级别的优点是更高的读性能,不需要