章
目
录
上篇文章我们探讨了分布式事务的二阶段提交,它虽然原理易懂、实现相对简单,但在实际项目应用中却存在诸多问题。本文我们将聚焦于二阶段提交的改进版本——三阶段提交,详细分析它的原理、优势以及仍存在的不足,这也是在面试中经常会被问到的。
一、二阶段提交的困境
二阶段提交分为准备阶段和提交阶段。在准备阶段,所有参与事务的节点都要完成各自的操作并锁定资源,但不提交事务;直到提交阶段,事务协调者确认所有节点准备就绪后,才通知各个节点进行全局提交,提交完成后节点才会释放资源。这一过程看似逻辑清晰,实则暗藏隐患。
- 性能瓶颈:由于各个节点在事务完成前一直处于阻塞状态,长时间占用数据库资源,导致系统整体性能下降。尤其是在高并发场景下,这种资源占用和阻塞会极大地影响系统的响应速度。
- 协调者单点故障风险:事务协调者在整个流程中至关重要,如果协调者出现故障,分支节点将无法收到提交或回滚的通知,只能一直等待,进而造成系统卡顿甚至瘫痪。
- 数据一致性问题:在网络不稳定的情况下,可能会出现部分节点收到提交通知,而部分节点未收到的情况,这就会导致数据不一致,严重影响系统的准确性和可靠性。
二、三阶段提交的改进措施
鉴于二阶段提交的种种问题,三阶段提交(3PC)应运而生,它将事务处理过程分为canCommit、preCommit和doCommit三个阶段。其实可以理解为,三阶段提交是在二阶段提交的基础上,对提交阶段进行了进一步细分,在准备阶段和最终提交阶段之间插入了preCommit(预提交)阶段。
- preCommit阶段的作用:在这个阶段,主要目的是提前确认各个参与者准备提交的状态是否正常。举个例子,在电商系统中,当创建订单和扣减库存作为一个分布式事务时,如果在扣库存环节发生服务宕机等故障,通过preCommit阶段的预提交尝试,就能提前发现问题,避免将问题留到最终提交阶段,从而减少不必要的资源浪费和潜在的数据不一致风险。
- 引入超时机制:这是三阶段提交的重要改进点。在二阶段提交中,只有事务协调者具备超时机制,而各个分支事务缺乏独立的超时控制。这就导致当某个分支事务出现长时间不响应(比如订单中心处理订单时一直无响应)的情况时,整个事务会被一直阻塞。而在三阶段提交中,每个参与者都有自己的超时时间。例如,设置等待时间为1 – 2秒,如果在preCommit阶段或doCommit阶段,参与者在等待超时后仍未收到协调者的指令,就会自动进入本地提交(doCommit)流程并释放资源,有效避免了事务的长时间阻塞。
三、三阶段提交仍存在的问题及应对方案
尽管三阶段提交在一定程度上改善了二阶段提交的弊端,但它并非完美无缺,仍然无法完全解决数据不一致的问题。比如,当某个参与者在自动提交(因超时触发)过程中出现提交失败,而其他参与者提交成功时,就会出现数据不一致的情况。以创建订单和扣库存为例,可能创建订单成功了,但库存扣减却失败了。
面对这种情况,目前常用的方法是采用兜底方案。可以先将触发的异常情况详细记录下来,然后反馈给后台,由人工进行干预处理,以此来尽量保证数据的一致性。
分布式事务的三阶段提交相较于二阶段提交,在性能提升、避免长时间阻塞等方面确实取得了一定的进步,但在数据一致性的处理上仍存在挑战。在实际的项目开发中,我们需要根据业务场景的具体需求和特点,权衡不同事务处理方式的利弊,选择最合适的方案。如果大家对三阶段提交或分布式事务的其他方面有任何疑问,欢迎在评论区留言讨论,让我们一起深入探讨,共同进步。