文章摘要(AI生成)
分布式环境中,由于数据分布在不同节点上和可能出现的网络故障、节点故障等问题,传统的单一数据库事务的ACID属性在分布式系统中难以保证。分布式事务主要解决一致性、原子性、隔离性和持久性问题。分布式事务通过一致性协议来确保一组操作要么全部成功,要么全部失败,保持数据的一致性。为确保一组操作的原子性,需要采用分布式事务协议如两阶段提交(2PC)或三阶段提交(3PC)。为保证各个事务之间的隔离性,分布式事务采用锁机制、版本控制等手段来实现。为保证持久性,分布式事务通过数据备份、数据复制等手段来保证一旦事务提交,其对数据库的改变是持久的。分布式事务通过全局事务或状态机来对分支事务进行编排,以保证分支事务的操作原子性。在CP系统中,分布式事务常见,以确保数据的强一致性。在AP系统中,对一致性要求相对较低,可能采用最终一致性或其他非事务性手段处理数据更新。存在不同的分布式事务协议,如二阶段提交(2PC)、三阶段提交(3PC)、TCC和SAGA模式等,根据不同的使用场景选择适合的协议。
在分布式环境中,由于数据分布在不同的节点上,同时有可能发生网络故障、节点故障等问题,传统的单一数据库事务的ACID属性在分布式系统中变得难以保证。分布式事务的引入主要解决以下问题:
- 一致性问题: 在分布式系统中,由于数据分布在不同节点上,可能导致不同节点之间的数据不一致。分布式事务通过一致性协议,确保一组操作要么全部成功,要么全部失败,从而维护数据的一致性。
- 原子性问题: 在分布式系统中,要保证一组操作的原子性,即要么全部执行成功,要么全部回滚,需要采用分布式事务协议,如两阶段提交(2PC)或三阶段提交(3PC)。
- 隔离性问题: 多个事务可能并发执行,而且在分布式环境中,需要保证各个事务之间的隔离性,防止相互干扰。分布式事务通过锁机制、版本控制等手段来实现隔离性。
- 持久性问题: 在分布式环境中,要确保一旦事务提交,其对数据库的改变是持久的,即使系统发生故障。分布式事务通过数据备份、数据复制等手段来保证持久性。
所谓分布式事务,即是为了管理各个子服务的分支事务,通过全局事务或者状态机的方式来对分支事务进行编排,以此来保证分支事务在操作上的原子性。而根据分支事务编排方式的不同,我们又将分布式事务分为不同的分布式事务协议。
在CP系统(强一致性系统)中,确实更强调一致性,即保证在分布式环境下的数据一致性。因此,分布式事务在CP系统中更常见,以确保数据的强一致性。
在AP系统(可用性优先系统)中,对一致性的要求相对较低,系统更注重保证可用性和分区容忍性。在这样的系统中,可能会采用一些放宽一致性要求的策略,例如最终一致性。这并不意味着完全不使用分布式事务,而是可能选择更轻量级、最终一致性的事务模型,或者采用其他非事务性的手段来处理数据更新。
二阶段提交-2PC
二阶段提交的命名是对于全局事务来讲的,全局事务只有准备和提交两个阶段。
准备阶段
协调者向所有参与者发送“准备提交”请求,等待参与者的响应。
分支事务执行实际的业务操作,但不提交事务。同时,将事务执行结果记录在本地日志中。
全局事务进入“准备提交”状态,等待参与者的执行完成的消息。
执行阶段
执行阶段如果所有参与者都发送了提交完成的消息,全局事务进入“提交”状态,否则进入“回滚”状态。
提交阶段
如果所有参与者都发送了“同意提交”消息,协调者向所有参与者发送“提交”请求,等待参与者的确认。
协调者向所有分支事务发送“准备提交”请求,等待分支事务的响应。如果所有分支事务都成功,则协调者向所有分支事务发送“提交”请求。分支事务收到“提交”请求后,提交事务。
回滚阶段
如果有任何参与者发送了“否定提交”消息,或者在提交阶段发生超时或错误,协调者向所有参与者发送“回滚”请求。
如果任何分支事务在准备提交阶段发送“否定提交”消息,或者在提交阶段发生超时或错误,协调者向所有分支事务发送“回滚”请求,分支事务回滚
三阶段提交-3PC
三阶段提交相比于二阶段提交,在分支事务上的交互并没有改变,只是全局事务增加了一个准备完成的阶段:
准备阶段
协调者向所有分支事务发送准备提交的请求。
全局事务进入“准备提交”状态,等待参与者的准备完成消息。
准备完成阶段
分支事务在接收到准备提交请求后,执行实际的事务准备操作,并向协调者发送准备完成的消息。与2PC不同的是,在3PC中,准备完成的消息可能是“准备提交”或“中止”两者之一。
全局事务进入“准备完成”状态,等待参与者的最终执行完成消息。
执行阶段
与2PC一样,也分为回滚阶段和提交阶段。如果所有参与者都发送了事务执行完成的消息,全局事务进入“提交”状态,否则进入“回滚”状态
回滚阶段
如果有任何分支事务在准备或提交阶段发生超时、错误或发送“中止”消息,协调者向所有分支事务发送“回滚”请求,分支事务回滚。
提交阶段
如果所有分支事务都成功,则协调者向所有分支事务发送“提交”请求,等待分支事务的确认。
如果所有分支事务确认提交,则事务提交;否则,协调者进入回滚阶段。
尝试-确认-取消-TCC
TCC可以说也是2PC的一个变体,只不过全局事务的状态分为了尝试、确认和取消三个状态
尝试阶段
全局事务进入“尝试”状态,各分支事务执行尝试操作。
分支事务收到try请求后,尝试执行事务,保存执行的事务日志,但是不提交。
确认/取消阶段
当分支事务全部尝试执行成功时,全局事务进入确认阶段;当分支事务部分尝试执行失败时,全局事务进入取消阶段
确认阶段
全局事务进入“确认提交”状态,各分支事务执行实际的事务提交操作。
取消阶段
全局事务进入“取消”状态,各分支事务执行事务回滚操作。
SAGA模式
发起阶段
- Saga的全局事务由一个或多个子事务(局部事务)组成。
- 发起阶段由一个特定的子事务(起始事务)发起。
执行阶段
- 各个子事务按照定义的序列或图形执行,可能是串行或并行。
- 每个子事务执行自己的操作,并可能引发其他子事务的执行。
补偿阶段
- 如果在执行阶段的任何点发生故障或全局事务需要回滚,将执行补偿操作。
- 每个子事务都有对应的补偿操作,用于撤销执行阶段中的操作。
不同协议的使用场景
总的来说,SAGA更使用在分支事务顺序执行的场景,而如果想要保证分支事务同时执行,则需要考虑2PC、3PC、TCC等模式
协议 | 使用场景 | 注意事项 |
---|---|---|
两阶段提交(2PC) | 需要强一致性的场景,全局事务的原子性是首要考虑的因素。 数据库间的事务操作,要求所有数据库要么都提交,要么都回滚。 小规模系统或对性能要求不是非常高的系统。 | 2PC可能存在的问题包括阻塞时间长、单点故障、网络分区时的不确定性等,因此在高性能和高可用性的要求下需要谨慎选择。 |
三阶段提交(3PC) | 需要在全局决策期间减少阻塞时间的场景。 对于网络分区或协调者失效等情况,能够容忍一定不确定性的系统。 对性能和可用性有一定要求的系统。 | 3PC引入的准备完成阶段可以减少阻塞时间,但仍然可能存在一些不确定性,需要在具体场景中进行权衡。 |
TCC(Try-Confirm/Cancel)模式 | 需要灵活处理事务的先决条件和后置条件的场景。 需要实现自定义的Try、Confirm和Cancel操作,适用于复杂的业务逻辑。 | TCC模式适用于对事务有更细粒度控制的场景,但实现相对复杂,需要考虑一致性、可靠性和性能等方面的问题。 |
Saga模式 | 需要支持长事务和异步补偿的场景。 业务逻辑需要分解为一系列顺序或并行的局部事务。 部分失败的场景,能够部分提交或部分回滚。 | Saga模式更加灵活,适用于需要定制化的业务流程,但要注意处理并发和异步操作的复杂性。 |
大多数场景我们都是解决分支事务并发的原子性,这也就是为什么Seata使用基于二阶段提交的AT模式,而不是SAGA模式。
附:AT模式流程示意图:
评论区