本文抄书自《深入理解分布式系统》第5章分布式事务。
什么是分布式事务
传统数据库的事务意义为,有一系列数据库操作,希望这些操作作为一个整体,要么全部成功,要么全部失败,同时不希望操作的中间状态暴露。
事务一般需要遵守ACID
- 原子性(Atomicity):一个事务包括的所有操作要么全部完成,要么全部不完成。如果中间步骤失败,那么回滚到初始状态。
- 一致性(Consistency):在事务开始之前和事务结束以后,数据库的完整性没有被破坏,即需要满足用户给出的约束条件,例如用户指示
A+B=100,那么数据库需要保证这一点。 - 隔离性(Isolation):数据库允许多个事务并发对数据进行读写/修改,隔离性防止多个事务并发执行时,由于交叉执行导致数据出现异常。隔离级别有多种。
- 持久性(Durabilty):事务结束后,对于数据库修改是永久的,出现故障也不能消失,即事务需要下盘。
对于一致性和持久性,单机和分布式区别不大,但是原子性和隔离性比较困难
- 原子提交:如果分布式系统部分节点失效,也需要回滚能力。
- 并发控制:通常涉及锁和多版本并发控制。
原子提交
分布式事务的原子性通过原子提交协议(ACP)实现,需要满足以下三个特性
- 协定性(Agreement):所有进程要么一起提交事务,要么一起终止事务,不能存在一个提交一个中止。
- 有效性(Validity):如果所有进程都决定提交且没有故障,那么整个系统将一起提交事务,一旦一个进程决定终止事务,那么停止提交。
- 终止性(Termination):分为弱终止条件和强终止条件,弱终止条件不允许故障,如果出现故障则需要阻塞等恢复;强终止条件则允许部分故障,非故障点继续。
两阶段提交
两阶段提交(2PC)的思想是,一阶段先检查所有节点状态是否满足事务正确性,二阶段根据一阶段结果决定是否事务操作。
两阶段提交包括协调者和参与者,其流程如下
第一阶段:准备阶段
- 协调者发送事务请求,并要求预提交。
- 参与者执行事务操作并锁定资源(如加锁,写入临时文件),防止其他事务修改。
- 参与者反馈事务提交状态,回复
YES或NO,超时也是NO。
第二阶段:提交阶段
- 如果全部回复
YES,参与者正式提交事务 - 如果存在
NO,参与者全部回滚事务
三阶段提交
三阶段提交是为了解决两阶段提交中存在的问题,流程如下
第一阶段:询问阶段 并行向所有参与者发送事务,询问是否可以执行提交操作,但不锁定资源。
第二阶段:预提交阶段
- 如果全部回复
YES,协调者发送预提交指令,参与者执行事务操作并持久化日志,但不提交。 - 如果存在
NO,则全部回滚事务。
第三阶段:最终提交 如果所有参与者在预提交阶段都成功,则全局提交并释放资源。 如果存在执行失败,则失败的参与者回滚事务。
优点:减少阻塞 :参与者在预提交阶段不锁定资源,协调者故障时可通过超时机制自主决策。 更高可用性 :通过超时机制避免单点故障导致的系统停滞。
缺点 :复杂度增加 :相比2PC,协议流程更复杂,实现和维护成本更高。潜在数据不一致 :极端情况下(如网络分区),超时机制可能导致部分节点提交而其他节点回滚。
总结 :3PC通过拆分阶段、引入超时机制和减少资源锁定时间,解决了2PC的阻塞问题,但以更高的协议复杂度为代价。其设计体现了一致性与可用性的平衡 ,适用于对容错能力要求较高的场景。