2PC时代即将结束,2PC只是提供原子性提交而不是事务本身 · Exactly Once


如果有分布式事务协议,那么每个软件工程师都知道它:“两阶段提交”,也称为2PC。尽管使用了几十年,但是由于缺乏云环境的支持,它却一直在稳步下降。
过去在相当长的一段时间里,它是构建企业分布式系统的实际标准。也就是说,随着云成为默认的部署模型,设计人员需要学习如何在没有云的情况下构建可靠的系统。
回答如何替换2PC的问题首先需要了解协议的含义。尽管它曾经很受欢迎,但围绕2PC仍存在许多误解。这篇文章旨在澄清其中至少一些。

2PC不提供“事务”
2PC是原子提交协议,这意味着如果所有参与者都投票“是”,则所有参与者最终都将提交,否则将使系统保持不变。当用户触发了提交操作完成后,要么应用了所有本地修改,要么都没有应用。提交可能要花很长时间才能完成,在某些失败情况下,它将永远挂起。
让我们看一个例子,看看“不提供事务”的含义。在我们的场景中,我们有两个参与者:数据库和消息队列。该图显示了两个参与者都投票“是”并且协调者正在提交。

我们的示例假定队列事务首先提交,但是2PC并没有说明参与者提交的顺序。它是不确定的,每次执行时可以针对同一组参与者进行更改。
最有趣的是外部观察者,即客户。它向两个参与者发出读取请求。消息队列的读取请求在协调器提交之后到达。这意味着读取操作将返回写入刚刚提交的事务中的队列的消息。
对于数据库,读取请求在提交之前到达。这将是什么结果?2PC对此行为一无所知- 不在协议定义的系统模型之内。读取行为不是由协议定义的,而是部署配置。
读取操作可以至少有两种可能的行为:

  • 阻塞直到提交本地事务-当本地事务以Serializable隔离级别运行时,将发生这种情况。这是Microsoft分布式事务处理协调器和Microsoft SQL Server 的默认配置,但是可以基于每个事务进行更改,
  • 返回最后的提交值(与本地事务写入的值不同)-当本地事务Snapshot隔离运行时,会发生这种情况。

总而言之,当存在使用2PC提交的事务以及在每个参与者级别运行的其他本地事务时,2PC不会提供系统中原子的原子可见性。确切的行为不是由2PC定义的,而是取决于协议的具体实现,所涉及的资源以及部署和运行时配置。

2PC实现高可用
任何不平凡的协议都定义了它可以容忍的故障条件,而2PC也不例外。2PC特有的是,某些类型的故障会使参与者“卡住死锁”。只要参与者投票“是”,就无法取得任何进展,直到协调员返回响应。
参与者卡住的原因可能是什么?首先,协调员的失败。其次,协调者和参与者之间的网络分区脑裂。卡住的可能性取决于协调器的可用性和网络故障的可能性。通过减少故障的可能性,我们可以使2PC的可用性更高。

这涉及已经提到的实现和配置方面。例如,在MSDTC中,协调器是单个进程,但可以在故障转移群集模式下部署。那是部署决定。2PC中也没有任何东西可以阻止将协调器实现为法定人数的流程。
最后,如果所有各方(协调者和所有参与者)都在同一本地网络上,单个群集上或单个VM内运行,那么网络分区的可能性是多少?
一如既往,环境为王。

提交延迟不是最大的问题
在2PC中进行提交需要协调者和每个参与者之间进行2次往返,并且生成了4n消息,其中n参与者的数量是多少。有时,这被认为是协议中许多实际问题的根本原因。这不是理想的选择,但只能解决其他更大的问题。
问题是锁定导致参与者级别的潜在争用,尤其是在处理关系数据库时。持有锁意味着处理给定状态的其他事务需要等待该事务提交才能取得任何进展。
这种情况在没有2PC的情况下就存在,但是协议使得情况总是最糟糕的,因为在2PC中,最慢的参与者定义了持有锁的时间。

2PC非常适合云端?
众所周知,云计算供应商在其服务内部使用2PC,并且在IaaS级别运行时用户可以使用2PC 。也就是说,没有任何一个云供应商在本地云服务级别上支持MSDTC和/或XA,即本地服务不能参与2PC。
通常,可用性和性能被认为是造成这种情况的原因。尽管这不是2PC的强项,但可以说安全(或缺乏安全性)更为重要。
2PC假定参与者和协调者之间高度信任。可以想象一个邪恶的用户操作特制的协调器,通过故意使事务挂起在“阻塞状态”来耗尽参与者的资源。
从云供应商的角度来看,这可能会带来非常有害的后果。根据协议,参加者在投票“是”后不得取得任何进展。因此,在恶意协调员的情况下,他们将不得不中断协议或允许其资源被阻止。
即使云供应商将他们的协调器作为唯一有效的选择,恶意的参与者仍然可能造成很大的伤害。使云服务能够充当2PC参与者有效地为拒绝服务(DoS)攻击打开了大门。
(单点风险)

2PC不是唯一的提交协议
2PC只是原子提交的一种可能解决方案。它在某些情况下工作良好,但在违反其假设的环境中使用时性能较差。
实际上,很少有2PC对参与者的假设。围绕事务确定性设置更多约束条件允许使用其他方法来最大程度地减少锁保持时间。
当我们认识到缺乏原子可见性时,会采取一些具体措施,例如根据消息队列的性质,确保一次性提交提交成功,也有可能最终要求一种对每个参加者实现一次性顺序写入的提交协议。

总结
希望这篇文章对2PC以及我们从协议中得到的内容有更多的了解。尽管2PC的时代即将结束,但是很高兴知道我们需要在构建的系统中通过其他方式提供什么保证。