2011-09-12 87 views
40

我相信大多数人都知道2PC(两阶段提交协议)是什么,以及如何在Java或大多数现代语言中使用它。基本上,它用于确保当您拥有2个或更多数据库时事务处于同步状态。两阶段提交

假设我在两个不同的位置使用2PC 2分的DB(A和B)。在A和B准备提交事务之前,两个DB都会向事务管理器报告,说他们已准备好提交。所以,当事务管理器被确认时,它会发回一个信号给A和B,告诉他们继续。

这是我的问题:比方说,A收到信号并提交交易。一旦完成一切,B即将做同样的事情,但有人拔掉电源线,导致整个服务器关机。当B重新上线时,B会做什么? B怎么做?

记住,一个致力于但是B不,我们正在使用2PC(因此,2PC的设计停止工作,不是吗?)

回答

43

在两阶段提交

两个阶段提交并不保证分布式事务不会失败,但它确实保证不会在TM没有意识到的情况下自动失败。

为了让B到报告这项交易为准备提交,B必须在永久存储的交易(即B必须是能够保证交易能够在所有情况下提交)。在这种情况下,B一直坚持交易,但交易经理尚未收到B的消息,确认B已完成提交。

事务管理器将再次轮询B时的B来到重新联机,并要求它提交事务。如果B已经提交了交易,它将报告交易已完成。如果B还没有提交交易,它就会提交,因为它已经坚持了它,因此仍然可以提交交易。

为了让B到在这种情况下失败了,那就要经历一个灾难性的失败是数据丢失或日志条目。交易管理者仍然会意识到B没有报告成功的提交。

在实践中,如果B可不再提交事务,这将意味着,这花了B发出灾害已造成数据丢失,而当TM要求它提交TxID添加B将报告的错误它并没有意识到或没有认为处于可交换状态。

因此,两个阶段提交不会阻止发生的历史灾难性故障,但它确实防止故障的忽视。在这种情况下,如果B不能提交,事务管理器会向应用程序报告错误。

应用程序仍然必须能够从错误中恢复,但成交离不开应用程序静默失败被意识到矛盾的状态中。

语义

  • 如果资源管理器或网络出现故障在阶段1, 事务管理器将检测到致命错误(无法连接到 资源管理器)和标记子交易失败。当 网络恢复时,它将中止所有参与资源管理器上的事务处理。

  • 如果资源管理器或网络中的第2阶段出现故障, 事务管理器将继续轮询直到 它回来了资源管理器。当它重新连接回资源管理器 它会告诉RM提交事务。如果RM沿'未知TxID'返回 错误,则TM将会知道 RM中存在数据丢失问题。

  • 如果TM在阶段1中出现故障,则客户端将阻塞,直到 TM恢复运行,除非它由于网络连接断开而超时或收到错误。在这种情况下,客户意识到 错误,并且可以重新尝试或启动中止本身。

  • 如果TM进入第2阶段下来,然后它会阻止,直到 以旧换新回来了客户端。它已经将交易报告为 可提交,并且不应向客户提交致命错误 ,但它可能会阻止,直到TM恢复。 TM仍然会以 的交易处于未提交状态,并将轮询RM 以在其恢复时提交。

资源管理器中的提交后数据丢失事件不由事务管理器处理,它是RM弹性的函数。

两阶段提交并不保证容错能力 - 请参阅Paxos了解确实解决容错的协议示例 - 但它确实保证分布式事务的部分故障不会不被注意。

  1. 注意,这种故障也可能会失去从先前提交的交易数据。两阶段提交并不能保证资源管理器不会丢失或损坏数据,或者DR过程不会搞砸。
+0

这个答案提出了[网络可靠]这个危险的假设(https://queue.acm.org/detail.cfm?id=2655736)。 –

+0

我不知道你在做什么。如果在第一阶段发生网络中断,TM将无法连接到其中一个RM并因致命错误而中止交易,最终告知所有RM在他们重新联机时中止。在第二阶段,它将继续轮询RM,直到网络恢复正常,此时它将发出确认提交。同样,2PC不保证提交,它只是保证事务不会失败,没有应用程序意识到它。 – ConcernedOfTunbridgeWells

+0

如果TM在收到所有投票提交后崩溃,但在发送最终提交/放弃之前会怎么样?然后每个人都拿着锁,等待投票。而且你不能超时,有些节点可能会提交而其他节点会超时并中止。如果你有一个同步可靠的网络,并且没有节点崩溃,并且你有实时操作系统,这样你就可以在有限的时间内保证进度,那么2PC就可以工作。通常,我们没有这些属性。 –

2

我相信三阶段提交是一个更好的方法。不幸的是,我还没有发现任何人实施这样的技术。

http://the-paper-trail.org/blog/consensus-protocols-three-phase-commit/

这里有上述文章的主要部分:

与2PC的主要困难是,一旦提交已决定由统筹制作,并传达给一些副本,复制品会直接前进并根据提交语句执行操作,而不检查每个其他副本是否收到该消息。然后,如果提交的副本与协调者一起崩溃,那么系统无法告诉交易的结果是什么(因为只有收到消息的协调员和副本肯定知道)。由于事务可能已经在崩溃的副本上提交,协议不能悲观地中止 - 因为事务可能具有无法撤消的副作用。同样,该议定书也不能乐观地强制交易承诺,因为最初的投票可能是堕胎。

这个问题 - 大部分情况 - 通过增加一个额外的阶段到2PC来绕过,毫不奇怪,给我们一个三阶段提交协议。这个想法很简单。我们打破2PC的第二阶段 - '承诺' - 分成两个子阶段。首先是“准备提交”阶段。当协调员在第一阶段收到一致的“是”票时,协调员会将此消息发送给所有副本。在接收到这些消息后,副本进入可以提交事务的状态 - 通过获取必要的锁等等,但最重要的是不做任何以后无法撤消的工作。然后他们回复协调员,告诉它已收到“准备提交”的信息。

此阶段的目的是将投票结果传达给每个副本,以便无论哪个副本死亡都可以恢复协议的状态。

该协议的最后阶段与2PC中的原始“提交或放弃”阶段几乎完全相同。如果协调员收到所有副本提交的“准备提交”消息的确认,则继续提交事务是安全的。然而,如果交付没有得到确认,协调员不能保证协议状态在它发生崩溃时能够被恢复(如果你容忍固定数量的故障,则协调器可以在接收到f + 1后继续确认)。在这种情况下,协调员将中止交易。

如果协调器在任何时候都应该崩溃,恢复节点可以接管事务并从任何剩余的副本中查询状态。如果已提交事务的副本已经崩溃,则我们知道每个其他副本都收到了“准备提交”消息(否则协调器不会移动到提交阶段),因此恢复节点将会能够确定交易能够被执行,并且安全地将协议安排在其结论之上。如果有任何副本向恢复节点报告尚未收到“准备提交”的副本,恢复节点将知道该事务没有在任何副本上提交,因此能够悲观地中止或重新运行协议从一开始就。

那么3PC是否解决了我们所有的问题?不完全,但接近。在网络分区的情况下,车轮相当不错 - 想象一下,所有收到“准备提交”的副本位于分区的一侧,而那些不在另一侧的副本。然后这两个分区将继续与分别提交或中止事务的恢复节点,并且当网络合并时,系统将具有不一致的状态。所以3PC和2PC一样有可能不安全的运行,但总是会取得进展并因此满足其活性特性。 3PC不会阻止单节点故障的事实使得它对于高可用性比低延迟更重要的服务更具吸引力。

+0

最好把链接文章的基本部分放在答案中,这样,如果链接被改变,信息不会丢失。 –

+0

为了实际的正确性,您应该在系统中真正使用Raft或Paxos而不是3PC。 –

3

尽管您付出了很多努力,但您的情况并非唯一可能最终出错的地方。假设A和B都向TM报告了“准备提交”,然后有人拔掉TM与B之间的界限,B正在等待TM的前进(或不进行),但它肯定获胜在TM重新连接之前不会永远等待(由于显而易见的原因,在整个等待时间内,涉及交易的资源必须保持锁定/不可访问)。所以当B为了自己的口味而等待时间过长时,它会采取所谓的“启发式决策”。也就是说,它会决定独立于TM来提交或回滚,呃,我不知道是什么,但这并不重要。显而易见的是,任何这样的启发式决策都可能偏离TM所做出的实际承诺决定。