2010-06-10 75 views
9

假设您有一个连接3个不同外部系统的应用程序。您需要全部更新3.如果发生故障,您需要回滚操作。 这不是一件很难实现的事情,但是说操作3失败了,当回滚时,操作1的回滚失败!现在第一个外部系统处于无效状态...几个无交易外部系统的原子操作

我在想一个可能的解决方案是关闭应用程序并强制外部系统的手动修复,但后来又一次...它可能已经有了使用这些信息(也许这就是为什么它失败了),或者我们可能没有足够的访问权限。或者它可能不是一个回滚行动的好方法!

是否有一些好的方法来处理这种情况?

编辑:一些应用程序的细节..

这是一个多用户的Web应用程序。大部分工作是通过预定的工作完成的(通过Quartz.Net),所以大多数操作都在它自己的线程中运行。某些用户操作应触发更新多个系统的作业。外部系统有些不稳定。

我想改变使用命令和机组工作模式

+0

外部系统是否固定?或者你可以修改它们吗? – bmargulies 2010-06-14 04:38:39

回答

1

两阶段提交(2PC)可能适合此处。

第一阶段是让各种数据库同意他们愿意继续提交。在你的例子中,数据库1将不会继续写入,直到它确信所有三个数据库都报告了事务可能。

与您所描述的过程相比,这是一种“乐观”的方法 - 数据库1将假定事务应该经过,直到它学习到了,否则将被迫回滚。

+0

谢谢。这有点像我已经使用UnitOfWork进行执行,提交和回滚,存储具有CanProcess可执行和撤消的命令。 – simendsjo 2010-06-17 09:39:03

0

取决于应用(单个用户对企业)的规模应用,关闭应用程序可能是一个坏主意。

首先,我建议将3个外部应用程序中要更改的信息的初始状态保存到本地存储到您自己的应用程序中。这意味着您至少可以确定应用程序崩溃/回滚失败时应该执行的回滚状态/ etc。一旦交易成功提交,您可以删除这些数据。

当其中一个操作失败时该怎么办取决于3个外部系统的功能。假设其中一个系统拥有员工数据。关闭应用程序仅仅是因为一个员工的地址由于交易失败而导致错误是矫枉过正的。只要访问员工的数据,简单地检查失败的事务日志(即保存3个外部应用程序的初始状态的本地存储)就好多了。如果该雇员数据被标记为无效,则抛出一个错误,指出该记录处于无效状态并且无法检索。

但是,如果整个外部系统由于失败的事务而陷入混乱,那么是的 - 这里没有什么可以做的,但是关闭应用程序直到问题得到解决。

1

您想进一步解释操作1的回滚可能会失败吗?

它想要达到的状态是之前的状态,所以它应该在逻辑上一致。可能会出现网络故障等暂时性问题,但最好的解决办法就是重试,直到问题消失。

如果问题在于后续事务在此期间锁定或更改了数据,那么您遇到的问题要大得多 - 您的事务不是原子性的,并且将它们回滚可能导致其他事务的输出失效。

0

Oddthinking的答案是一个好的,但有限,因为它是很难可靠做一个2PC。这在分布式计算社区中已经有很长一段时间了,尽管很多人都尽力忽略它。

如果您有兴趣深入研究这个领域,Paxos consensus algorithm是一个很好的开始。并且要意识到,这是一个令人惊讶的难题,正是因为你提到的两个问题以及实际上不可能建立一个真正可靠的消息传递系统,它可以在有限的时间内传递消息。 (要理解为什么这是真的,考虑someone with a backhoe可能会消灭各通信方之间的所有网络链接...)

我怀疑真正的修复是设计整个系统的体系结构以及如何在整个系统中推出更改一个地区的通信损失不是灾难性的。这可能也可能不容易,具体取决于具体细节。