5.5.2 分布式事务解决理论 2PC
如果我们要设计一个强一致性的 CP 架构系统,该如何实现呢?针对强一致性的分布式事务场景,出现了二阶段提交以及三阶段提交协议的解决方案。
二阶段提交协议(Two-phase Commit Protocol,简称 2PC)是一个基于协调者的强一致性原子提交协议。 两阶段提交协议在分布式系统中被广泛应用于解决分布式事务相关问题。目前大部分关系数据库都是用二阶段提交来完成分布式事务,例如 Oracle、MySQL 所支持的 XA 协议也可归类于两阶段提交协议。
1. 二阶段协议概述
在分布式系统中,由于分支事务只能知道自己执行的结果,并不知道其他分支事务的执行情况,因此需要设计一个协调者的角色,各个分支事务向协调者上报执行状态,再由协调者根据各个分支事务的执行结果决定全局事务的提交或回滚。
两阶段提交协议,顾名思义由两个阶段组成,即准备阶段和提交回滚阶段。第一阶段用于各个分支事务的资源锁定,第二阶段用于全局事务的提交或回滚。
1.1 第一阶段:准备阶段
二提交第一阶段为准备阶段,又称为投票阶段,由协调者向参与者发起请求,以询问当前事务是否能正确处理,当参与者收到请求后,开启本地数据库事务,执行分支事务的具体内容,但此时并会提交分支事务。参与者根据执行分支事务的结果,反馈给协调者 YES 或 NO,表示该分支事务是否可正确提交。
1.2 第二阶段:提交/回滚阶段
在准备阶段,参与者向协调者汇报 YES/NO 两种状态。而在阶段二,也有对应两种处理方式:提交全局事务或回滚全局事务。
协调者在超过约定的时间内没有收到全部参与者的响应时,或者收到所有参与者的响应中存在状态为 NO 时,便会发起全局事务回滚。如果收到所有的分支状态都有 YES,便会发起全局事务提交,同时向客户端返回全局事务结果,并结束本次事务。
2. 二阶段协议的优缺点
两阶段提交逻辑设计容易理解、逻辑清晰简单,但在实际场景中也存在不少问题,主要包括以下三点:
- 同步阻塞问题:两阶段提交协议的阻塞主要体现在参与者需要协调者的指令才能执行第二阶段的操作。当协调者发生故障时,参与者在第一阶段锁定的资源将一直无法释放。
- 潜在数据不一致风险:在第二阶段,如果因为网络异常导致一部分参与者收到 Commit 请求,而另一部分没有收到 Commit 请求,那么结果将是部分参与者提交了事务,而另一部分参与者无法提交。
- 单点问题和脑裂:
- 单点问题:二阶段提交过于依赖协调者,当协调者发生故障时,整个集群将不可用。
- 脑裂:当集群出现多个协调者时,将无法保证二阶段提交协议的正确性。