WS-TX,自 2001 年以来第三次尝试建立 Web Service 事务标准,在五月份获得批准成为了 OASIS 的正式标准。上周 Evan H. 在 MSDN 分布式事务及服务论坛上提出的问题引发了一场争论:
分布式事务(即 WS-Transaction)是否违背了面向服务架构的“自治”信条?
事务的目的是让两个或更多软件代理在合作完成一个工作单元的时候能够保持状态的一致,而无论该工作单元的执行结果是失败(由于业务或技术错误)还是成功。
事务标准通常由三个部分组成:
- 上下文管理(Context Management)设施,用于管理多个事务实例间的共享状态。状态可按值传递也可按引用传递
- 协调(Coordination)设施,用于提供事务参与者的注册和事务协议管理
- 事务协议(Transaction Protocols),它们是达成状态一致性的关键(无论是发生了通讯错误还是一个或多个参与者抛出了业务异常)
按照 WS-TX 的设计,上下文管理设施和协调设施担负着事务协调者的责任,另外 WS-TX 指定了两个事务协议:WS-AtomicTransaction(WS-AT)和 WS-BusinessActivity(WS-BA)。
“[OASIS] 技术委员会认识到不存在一个能够适应所有情况的事务模型,因此 WS-Transaction 定义了一个可扩展的协调框架,既能够适应经典的两段式提交,也能够适应一些限制更宽松的事务,它们的隔离(isolation)行为做了调整,较适宜松耦合系统。”WS-TX 工作组的联席主席 Ian Robinson 说。
Choreology 提供的《事务协议的分类》值得一读。按照其中的分类法,WS-AT 属于“暂时先做再等确认(provisional-confirm)”类,而WS-BA 属于“先实行再补偿(do-compensate)”类。请注意我认为WS-AT 不满足ACID,因为WS-AT 放宽了对隔离性的要求。WS-TX 的目标就是让用户可在“暂时”与“彻底”之间选择需要的行为。
因此服务可在满足自治性的同时又能实现事务协议来协调该服务参与的工作单元。这是否会妨害可伸缩性呢?答案是肯定的,因为状态一致性是以在事务参与者和协调者之间交换额外的消息来达成的。
在MSDN 论坛上的辩论集中在两个观点上: IDesign.net 的首席架构师 Juval Löwy 提出,在执行一个普通的工作单元时,如果牵涉到若干个软件代理,那么没有状态一致性我们就没法完成提交,而且为了达成状态一致性而重新发明特别的事务协议不一定是个好主意。他的观点是如果可行,采用原子性事务会比较好,因为它比较简单(请注意WS-BA 为了达成事后补偿需要由协调者来管理一些特殊逻辑)。然而,如果你无法在工作单元的执行期间维持一个暂时状态(provisional state),那么你不得不采用其他协议,比如像WS-BA 这样的“do-compensate”协议。必须权衡的是只有在你能够“容忍误差”的情况下这个协议才可行。
另一方面,Roger Sessions、Ollie Richies、Ahmed Nagy 和 Arnon Rotem-Gal-Oz 争辩说:
“跨服务的事务是糟糕的想法”……“你真的希望让事务在地理上相距甚远的多个服务、多个信任授权、以及异质的执行环境之间往返穿梭?我知道我不会这样做。”
他们都针对使用数据库锁来实现 WS-AT 提出了警告。Arnon 提议我们应该用两个不同的名字来区分数据库级别的事务和所谓“长期运行的事务”。这种交互活动通常称为“Sagas”。
刚刚回到微软的 Pat Helland(虽然他没有参与论坛里的讨论),在对比数据库事务和 SOA 事务的时候,作了一些澄清。
在数据库内部,当前事务提供了清晰干脆的“此刻”的含义,对数据意义的解释即着落在“此刻”。当你身处在事务中间,除非发起这次事务的当前正运行的应用程序改变了数据,否则一切都会维持原样。
在 SOA 中,我们都承认存在独立的机器。[即“自治”]
当系统 A 向系统 B 发送一条消息,消息中包含的数据会在发送前被解锁。这就意味着这个数据成了历史遗迹。系统 B 只能看到来自系统 A 的数据过去的样子。这就是这些不共享事务的独立系统的一个本质方面。
除了隔离性,Pat 还认为在处理分布式事务的时候,强制一致性约束可能并不是最有效的办法:
我看到业界越来越愿意放宽一致性的要求,甚至超过我前面提到的程度。他们宁愿偶尔得到错误的数据,因为这样更划算。
许多公司声称他们从没用到事务协议和事务协调者来达成状态的一致性,但实际上他们用了,只不过不是符合 XA 的两段式提交事务协议。他们的系统通常会记录被调用的操作,以及操作的结果。在晚一点的时候,代理会执行清理工作,任何失败的操作都会被回滚。在这种情况下,由于不必在工作单元的执行期间增加与事务协议相关的额外通讯,因此可伸缩性获得了提高。“事务协议”实际上是离线进行的。我的一位朋友曾为一家大计算机制造商工作,他告诉我说当协调代理不能回复到满意的状态时,他们打算“贿赂用户“,让用户成为他们的事务协议的一部分,幸好,他们还没有遇到过这种状况!
总而言之,似乎在这场争论中每个人都是对的。WS-AT 和 WS-BA 对 SOA 来说都是有效的事务协议。两者都不会破坏参与者的自治性。不过在使用 WS-AT 的时候,试得到完整的 ACID 性质是不明智的(WS-AT 对此并不要求)。隔离性,即让一个操作调用不受到属于另一个工作单元的其他操作调用的影响,通常是非常昂贵的,而且是绝大多数伸缩性问题的来源。在数据库中,隔离性的实现一般是通过将处理收到的请求的过程进行某种形式的串行化,在 SOA 的世界里,这几乎总是不可接受的。Pat 建议我们甚至应该更进一步放宽对一致性的要求,这也是一个正确的方向,因为当参与者是被动态地组织到任意工作单元的时候,要想强制实施业务规则也许是行不通的。这里强调了事务参与者的自治观念。不过状态一致性是 SOA 的基本,无论你打算如何实现它,你都需要把上下文管理设施、协调者以及操作调用协议(即事务协议)聚集到一起。
评论