Web Service 实现分布式事务

首先要声明,不推荐在web service中实现分布式事务。
原因如下:
  1、webservice在通信层上是一种无连接的协议,每两次调用之间,tcp连接是断开的。而分布式事务需要保存事务上下文,这是一个难点
  2、web service是一种以松耦合为指导思想的集成方式,一般主张采用无状态方法,一次请求即完成一次完整的处理,两次调用之间没有上下文关系;
    而事务处理更强调多次调用间的紧耦合关系
  3、异构平台不一定都支持两段事务提交模式。

一般的面向DCOM的分布式应用中,分布式事务支持策略如下:
  采用两段式事务提交的办法,第一次提交是预提交,预提交之后是可以回滚的。
  第二次提交是永久性的提交,提交之后就不可以回滚。
  并且,如果预提交成功,第二次提交也必然成功,系统必须可以保证这一点。

如果一定要实现分布式事务,相应的应对措施如下:
  1、针对web service的无状态连接,采用session机制保持事务上下文;或在服务器中维护应用程序级的事务池。
  2、对于松耦合系统之间的事务处理,可以将事务控制器独立出来,
    建立一个专用于分布式事务控制的应用,而用WEB SERVICE的方式公布接口,
    允许其他应用程序通过向这个事务控制器注册自己的两段式事务开启、提交和回退的web service接口。
    然后,当有客户想启动分布事务时,就可以向这个事务控制器发起分布式事务请求,选择事务各方,启动一个分布式,
    最后向事务控制器,而非是各个事务方直接发起提交请求,这样事务控制的多态就可以在事务控制服务器中实现,
    虽然实现可能还是通过查表等方式实现,而非平台级的抽象方法,但是对于事务客户来讲,这样一个服务器就是多态的实现部分。
  3、针对不支持两阶段事务的异构系统,不得已,需要改造它们以实现两阶段事务提交。
    推荐的改造办法:
      1)通过数据缓存的方式来实现。
        一般的N层结构的中间件产品中,都会提供两个级别的事务,即面向缓存中对象的事务控制和面向持久化过程的事务,
        可以考虑简单地将此两个事务级别对应的分布事务中的两段事务提交。
      2)用保存对象的历史状态来实现事务的手工回退。

-----------------------原文------------------------------------

因为这个问题讨论起来内容比较多一些,所以另开一个话题。
 
    如果你只是要解决两个系统之间的事务同步问题,可以采用判断服务是否成功的办法来解决,即:
    
    * A系统开始自己的事务,处理自己的数据,然后。。。
    * 在提交之前调用B系统的服务。
    * B系统开始自己的事务B,在事务中处理数据,再提交事务。
    * B系统把自己事务的提交成功与否的信息做为返回值回馈A系统。
    * A系统根据B的事务成功情况决定自己的事务是否提交或是回滚。
 
    但是,在继续深入讨论这个问题之前,先反问一个引伸的问题:当分布式系统之间,要进行事务控制的子系统不是两个,而是N个时,如果进行事务控制?
 
    分布式事务一直都是很难解决的问题。在面向DCOM的分布式应用中,有一种分布带事务支持策略,大体的思路是采用两段式事务提交的办法,第一次提交是预提交,预提交之后是可以回滚的。第二次提交是永久性的提交,提交之后就不可以回滚。并且,如果预提交成功,第二次提交也必然成功,系统必须可以保证这一点。
 
    这样,当每个系统都支持这种两段式提交之后,就可以采用这样的事务管理:一个控制角色向每个分布系统提出执行要求,并要求完成第一次事务提交。当每个系统的第一次提交都成功时,则要求所有系统完成最后的永久提交,可知这次的永久提交是肯定可以完成的,因此不须要再担心这次提交是否成功。
    如果第一次提交中,有某些应用出现失败,则要求所有的应用都回滚事务。
    一些数据库软件本身就支持事务嵌套,如sqlserver等,不幸的是,我们的主力数据库informix不支持。
    为了简化这种分布式事务管理,有一些中间件产品可以采用,用得比较广泛的是MS DTS.
 
    你可能已经看出来了,这样的事务控制策略虽然可以在分布式环境下满足事务的ACID要求,但是它对各个分布组件是有要求的,在基于COM, remoting,JRMI一类技术的分布式应用程序中,这个没有问题。但是在采用web service的场景中,这是有问题的。
 
    问题1. web service是一种以松耦合为指导思想的集成方式,一般情况下,主张采用无状态方法。
    webservice主张两次调用之间没有上下文关系,即一次调用与其他之前和之后的调用都没有关系,一次提交即完成一次完整的处理。但是分布式事务却要求各方要在两次对话之间保持对话状态,以便于知道本次永久性提交时,要对之前“哪一个”已经被预提交成功的事务执行最后的提交。
    当遇到这个问题时,我们必须要再多问自己一个问题:我们已经选择了正确的集成技术吗?如果多个系统之间有如此紧密的事务耦合关系时,我很怀疑它们其实就是同一个应用系统。同一个应用系统中,应该有相同的平台,相同的进程空间,相同的数据模型以及数据源。这种情况下,采用web service是一种错误的选择,web service应该用于不同平台、不同应用、不同的数据模型的系统集成。即便是的确需要在同一个应用系统中由于某些原因而实现模块间的分布式构造,也应该采用同一技术平台内的远过程访问技术,它们能通常比web service能提供更好的耦合性支持。
 
    好吧,假设你经过思考之后,对上述问题的回答是“是”:我们确实必须要在异构的、多平台的、本来应该是低耦合系统之间实现分布式事务控制。那么,webservice还有用处吗?
    谢天谢地,web service虽然主张交互之间采无状态方式,但是它并不是禁止采用有状态的交互。WEB SERVICE还是一种web技术,而web技术中的状态保存可能是最早被解决的问题之一了。在所有的web开发技术平台中,都有session机制,无论这些Session是通过IP,cookies, hidden input来实现,还是url sessionid来实现的,反正都有办法实现,请参阅所用平台的session支持机制就可以了。退一万步,你也可以通过在服务器中维护一个应用程序级的事务池来实现,未最后提交的事务对象都放在里面,每一个事务对象都给定一个唯一个的标志ID来识别,形成一个字典对象池。如果启动事务成功,则把此事务的ID返回给调用者执有,做第二段提交时,把事务的ID做为参数提交就是了。(随便提一下,用这种方法时,千万不能把对象的指针、句柄、引用什么的平台相关的值交给客户方,倒不是害怕安全问题,而是这些值在分布系统中是没有意义的,上次返回的指针没准早被垃圾收集机挪到其他地方去了)
 
    无论如何,webservice在通信层上是一种无连接的协议,每两次调用之间,tcp连接是断开的,因此,一但采用session机制来管理上下文,你就必须为这些session的生命期负责。试想,如果一个事务上下文已经开启,而此时客户方系统却突然当机了,这时会出什么事情?在同一个应用程序域中,客户方的当机会让连接中断,服务器立即就会中断并回退事务,但是在webservice里,状态管理机无法立即感觉到此事务的调用方已经失去控制,只能在一定的时间之后,才发现:“噫?这个事务已经N长时间没有人访问了!快快回退!”在ASP.net里,默认的状态超时时长大概是20分钟,JSP也差不多,阻塞了20分钟的事务对数据源是什么影响可想而止!因此,必须考虑合适的状态时长与事务隔离级别,以减小对数据源的性能影响。       
 
    问题2. web service的“反模式”方法论使得无法在系统之间统一出共同的抽象接口。
    web service是一种“反模式”的系统架构思想,即不是一般的由先建模并抽象接口开始,再由各个分布系统实现接口的系统构造方式,而是反过来:系统可能早已经完成,现在的问题是两个系统间的信息交互作用,因此交互的接口规格是根据需要,把系统数据模型去范式化后挑挑捡捡而定的。
    因此,webservice中不支持接口抽象,即:你无法定义一个各个系统都必须实现的抽象事务接口,然后由各个系统实现这个接口的多态,最后在承担事务控制器的应用中调用统一事务接口以调度分布事务。虽然这样的接口模型在很多面向对象的开发平台中的远过程调用技术中所支持,但是如同之前说过的,web service是一种用于集成的松耦合的反模式方法论,而不是为紧耦合系统中的分布式对象而设计的。
    所以,虽然有点讨人烦,但是我又一次忍不住想问我已经问过的那个问题:我们真得用对了技术吗?如果多个系统之间需要如此级别的接口耦合性,我真得越来越怀疑它们其实就是同一个应用系统了。
    假设你的回答还是“是,他们真得不是同一个系统,他们是异构平台的,异构数据的!”好吧,那么继续。让我们采用web service来完成集成,但是你必须忘记你的OOP思想,老老实实地编码,用枯燥的、重复的代码把所有的系统的事务都控制在一起,别想用对象抽象的概念来省一点事。
    真的吗?
    如果把事务控制器独立出来如何?假设我们建立一个专用于分布式服务控制的应用,而用WEB SERVICE的方式公布接口, 允许其他应用程序通过向这个事务控制器注册自己的两段式事务开启、提交和回退的web service接口。然后,当有客户想启动分布事务时,就可以向这个事务控制器发起分布式事务请求,选择事务各方,启动一个分布式,最后向事务控制器,而非是各个事务方直接发起提交请求,这样事务控制的多态就可以在事务控制服务器中实现,虽然实现可能还是通过查表等方式实现,而非平台级的抽象方法,但是对于事务客户来讲,这样一个服务器就是多态的实现部分。
    如果真得比MS更快更好地实现这样一个web service做接口,面向异构系统的分布式事务控制器,NASDAQ也许会有你的一席之地吧!
 
    问题3. 异构平台不一定都支持两段事务提交模式。
    web service面向的是完全异构平台的集成,那么显然不能指望每个平台都能支持两段时提交事务模式。但是,标准就是标准,协议就是协议,标准就是用来让大家遵守的,如果一个平台本来不支持两段式事务,那么为了能支持分布式事务,它就必须改造以实现两段式事务提交。
    怎么改造是各个应用系统内部的事情,为了本文讨论的全整性,也在这里稍微涉及一下。
    首选的方式是通过数据缓存的方式来实现。很多OO系统中,都采用了所谓的N层架构,即把业务对象与关系表模型分离开来,业务对象位于系统内存或是缓存中,由运行时的对象容器管理,容器根据一定的策略,把缓存中业务对象向数据库这样的久永介质中保存,或是从数据库中加载所需要的业务对象,在保存和加载过程中,将完成对象到表数据的转换,或是相反。

    一般的N层结构的中间件产品中,都会提供两个级别的事务,即面向缓存中对象的事务控制和面向持久化过程的事务,可以考虑简单地将此两个事务级别对应的分布事务中的两段事务提交。但是,这种方式必须冒一定的风险,如对象容器级的事务成功,而数据库事务提交时出现失败,此时将会导致的数据不一致的风险,尽管这个几率并不很大。

    在使用数据容器的情况下,也可以用保存对象的历史状态来实现事务的手工回退。因为在业务对象层与持久化层相分离之后,持久化层在数据更新时并没有复杂的逻辑,只是一些被罗列的、业务意义无关的数据更新序列。如果可以保持对象的状态历史,那么就可以在需要的时候将对象的状态恢复到旧的旧版上。实际上,在一些出色的中间件平台中,这个机制已经实现得非常完善了。(可以参阅Graphtalk平台的对象持久化管理,简直是天才!)

    另一种笨办法是通过数据逻辑来实现两段事务提交,例如在要求第一次提交时,即真正提交,在第二次提交时固定什么也不做,而返回正常。如果要求回退,那么就通过数据逻辑或是业务逻辑来更新数据为旧状态。这种实现方式绝对是很令人头痛的。

    不过,幸亏我们不是在为一个通用的数据库设计两段事务机制。要知道,面向服务的事务处理并不是如同数据库级别的事务那样,在事务的期间数据的操作有无穷的可能性。通常我们一个服务就是一个功能,其数据操作过程中,数据的变化方式是可预知的,因此恢复数据的状态也是一个个具体而固定的过程,只要我们针对每一个服务操作设计数据恢复机能就是了。

    最后,如果这些都不可能实现的话——大于50%的可能性,因为时间、成本、技术等原因,这些都实现不了,那么只能靠两个字了:妥协。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/439213.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【LeetCode每日一题】2024. 考试的最大困扰度

​​​​​​力扣 解题报告: 因为只有T和F两个元素,不难证明单向性。尺取法解决。当然这题也可以二分。 AC代码: class Solution { public:int maxConsecutiveAnswers(string answerKey, int k) {int l 0, r 0;int T 0, F 0;int ans …

使用WebService如何实现分布式事务

在 System.EnterpriseServices 名称空间中实现了COM服务的相关类,其中就提供事务支持。 你可以在你的方法上加上TransactionAttribute特性标记,那个方法就支持事务了。 然后在那个方法中就可以用ContextUtil.SetComplete()和ContextUtil.SetAbort()方法分…

【Leetcode - 172】阶乘后的零(思维)

给定一个整数 n ,返回 n! 结果中尾随零的数量。 提示 n! n * (n - 1) * (n - 2) * ... * 3 * 2 * 1 示例 1: 输入:n 3 输出:0 解释:3! 6 ,不含尾随 0 示例 2: 输入:n 5 输出&…

linq、lambda、entity framework之间的关系

lambda: 一种匿名委托的精简版写法,明显的标志是>符号 entity framework(简称EF): 微软访问数据库的最快捷最成熟的框架(ORM),在EF出现以前有SqlHelper、NHibernate等访问数据库…

2022-08-20-网易笔试题

写在前面 题目收集来源自网络,前四题是开发岗的,后四题是算法岗的,因为代码无处提交,不一定正确,就不贴出来了,这里只写一下我的思路吧~欢迎大家一起讨论~~ 1、 思路:因为最大1e9&#xff0c…

TUN/TAP设备浅析(一) -- 原理浅析

TUN/TAP设备浅析 TUN设备 TUN 设备是一种虚拟网络设备,通过此设备,程序可以方便地模拟网络行为。TUN 模拟的是一个三层设备,也就是说,通过它可以处理来自网络层的数据,更通俗一点的说,通过它,我们可以处理 IP 数据包…

2022-08-21 星环科技-C++开发笔试

1、 思路:拓扑排序,不解释了 2、 思路: 本来以为他是一个图论问题,找最大环。 但其实对于这种情况,他是要输出0的,而不是9,所以他不是一个图论问题,他带有顺序性,这种可…

TUN/TAP设备浅析(二) -- TUN/TAP的编程

这篇文章想详细阐述一下有关于 TUN/TAP 设备的编程。 其实关于这两种设备的编程,基本上属于八股文,大家一般都这么干。 启动设备之前 有的linux 并没有将tun 模块编译到内核之中,所以,我们要做的第一件事情就是检查我们的系统是…

【算法练习题】位运算(贪心)

题目: 解题报告: 首先预备几个结论: 1、对于两个数a,b ,生成a&b和a|b,则一定对应一个常数c,使得生成的两个数分别是ac和a-c。 2、对于两个数a,b,生成a&b和a|b的前后,二进…

TUN/TAP设备浅析(三) -- TUN/TAP设备的应用

上一篇文章主要讲述了TUN/TAP设备的一些原理,你可能会好奇,TUN/TAP设备究竟有什么用处呢?所以这篇文章,我想用一些实际的例子来回答这个问题。 例子源自陈硕老师的博客,博文中关于TUN/TAP设备的使用非常典型&#xff…

【20220903-美团笔试】

参考:20220903美团笔试题解_笔经面经_牛客网 前两个签到题就不整理了 第三题: 给定一棵有n个节点的树,节点用1,2,…n编号。1号节点为树的根节点,每个节点上有一个用大写字母表示的标记。求每个 节点的子树中出现的字母标记种类…

云计算底层技术-虚拟网络设备(Bridge,VLAN)

openstack底层技术-各种虚拟网络设备一(Bridge,VLAN) openstack底层技术-各种虚拟网络设备二(tun/tap,veth) Linux BridgeBridge与netfilterVLAN VLAN设备原理及配置VLAN在openstack中的应用IBM网站上有一篇高质量文章Linux 上的基础网络设备详解。本文会参考文章部分内容&…

【Codeforce-911D】逆序对

题干: Problem - D - Codeforces 解题报告: 不难发现,假设n的倒序排列(n,n-1,...,3,2,1)的逆序对是x,则对n的任意一个逆序对数为y的排列做翻转,新生成的排列的逆序对数位x-y。 因此这题作为奇偶性,其实只…

【LeetCode-面试题 17.09 - medium】第 k 个数

力扣 解题报告: 法一:优先队列做bfs。 法二:看成三个有序链表,做三路归并即可。 注意这里归并,如果多个指针最小值,那么这些指针都需要

10分钟精通SharePoint-验证方式

简介 说到身份验证大家应该不陌生,访问任何平台或系统都需要身份验证,SharePoint也不例外,用户身份验证可根据身份验证提供程序验证用户的身份,身份验证提供程序包含用户平局切可以确认用户正确提交这些平均的目录或数据库。用于…

【18周-钻石】能量供应

思路: 总纲是贪心,按终点排序,然后优先往右边排能量塔。具体实现的时候需要单点更新,区间查询,所以用树状数组set维护一下,就OK了。 代码:(不知道为啥有一个样例RE了) …

【LeetCode-2421(hard)】好路径的数目

解题报告: 提供两种解法:1、并查集。2、启发式合并。3、树分治(点分治,但是校招应该不会问到这个难度吧,,不复习了就) 解题思路1: 两种思考方式可以想到这个解法。 1、【由特解到…

分布式事务解决方案框架(LCN)

事务概念 事务特性(ACID) 原子性(A) 所谓的原子性就是说,在整个事务中的所有操作,要么全部完成,要么全部不做,没有中间状态。对于事务在执行中发生错误,所有的操作都会被回滚,整个…

C#分布式事务解决方案-TransactionScope

引用一下别人的导读: 在实际开发工作中,执行一个事件,然后调用另一接口插入数据,如果处理逻辑出现异常,那么之前插入的数据将成为垃圾数据, 我们所希望的是能够在整个这个方法定义为一个事务,Tr…

【19周-星耀】FASTER!FASTER!FASTER!

题目: 解题报告: 看数据范围,应该是个n^3的dp。 但是刚开始觉得二维就可以写。 但是G了,因为无法根据定义的状态判断从[i]到[i1]的速度是多少。我这直接默认是d[i]了,但是显然不一定是。 然后感觉欸,我是…