我相信三阶段提交是一种更好的方法。不幸的是,我还没有找到任何人实施这种技术。
http://the-paper-trail.org/blog/consensus-protocols-three-phase-commit/
以下是上述文章的基本部分:
2PC 的根本困难在于,一旦协调者做出提交决定并与某些副本进行通信,这些副本就会继续执行提交语句,而无需检查是否每个其他副本都收到了消息。然后,如果提交的副本与协调者一起崩溃,则系统无法告知事务的结果是什么(因为只有协调者和收到消息的副本才能确定)。由于事务可能已经在崩溃的副本上提交,因此协议不能悲观地中止——因为事务可能具有无法撤消的副作用。同样,协议不能乐观地强制事务提交,因为最初的投票可能是中止。
这个问题——主要是——通过向 2PC 添加一个额外的阶段来规避,不出所料地为我们提供了一个三阶段提交协议。这个想法很简单。我们将 2PC 的第二阶段——“提交”——分成两个子阶段。第一个是“准备提交”阶段。当协调者在第一阶段收到一致的“是”票时,它会将此消息发送给所有副本。收到此消息后,副本进入一种能够提交事务的状态——通过获取必要的锁等——但至关重要的是,它们不会做任何他们以后无法撤消的工作。然后他们回复协调员,告诉它“准备提交”消息已收到。
此阶段的目的是将投票结果传达给每个副本,以便无论哪个副本死亡,都可以恢复协议的状态。
协议的最后阶段与 2PC 中最初的“提交或中止”阶段几乎完全相同。如果协调者收到来自所有副本的“准备提交”消息的传递确认,则可以安全地继续提交事务。但是,如果未确认交付,则协调者无法保证协议状态在崩溃时会恢复(如果您要容忍固定数量的失败 f,则协调者可以在收到 f+1 后继续确认)。在这种情况下,协调者将中止事务。
如果协调器在任何时候崩溃,恢复节点可以接管事务并从任何剩余的副本中查询状态。如果已提交事务的副本崩溃,我们知道每个其他副本都收到了“准备提交”消息(否则协调器不会移动到提交阶段),因此恢复节点将是能够确定事务能够被提交,并安全地引导协议完成。如果任何副本向恢复节点报告它尚未收到“准备提交”,则恢复节点将知道该事务尚未在任何副本上提交,因此将能够悲观地中止或重新运行协议从一开始就。
那么3PC能解决我们所有的问题吗?不完全是,但它很接近。在网络分区的情况下,轮子会脱落——想象所有收到“准备提交”的副本都在分区的一侧,而那些没有收到的副本在另一侧。然后两个分区将继续与分别提交或中止事务的恢复节点,并且当网络合并时系统将具有不一致的状态。所以 3PC 和 2PC 一样具有潜在的不安全运行,但总会取得进展并因此满足其活性特性。3PC 不会阻塞单节点故障这一事实使其对高可用性比低延迟更重要的服务更具吸引力。