一文彻底搞懂分布式事务解决方案
分布式事务是指跨多个节点、多个数据存储或多个服务之间进行的事务操作。在分布式系统中,由于数据和服务的分散性,事务操作可能涉及多个资源,因此需要特殊的机制来确保事务的一致性、隔离性、原子性和持久性(ACID 特性)。
1. 什么是事务
事务是指一组操作被视为一个单独的工作单元,要么全部执行成功,要么全部执行失败。在数据库系统中,事务具有以下四个特性,通常称为 ACID 特性:
-
原子性(Atomicity):事务中的所有操作要么全部完成,要么全部撤销。如果事务的任何一部分操作失败,整个事务都将被回滚到初始状态,不会留下任何部分完成的结果。
-
一致性(Consistency):事务的执行使数据库从一个一致性状态转变到另一个一致性状态。这意味着事务在执行之前和之后都必须遵守数据库的约束和规则,如主键约束、外键约束、唯一约束等。
-
隔离性(Isolation):事务的执行不会受到其他并发事务的影响。即使多个事务同时运行,它们也应该像彼此顺序执行一样,每个事务应该感知不到其他事务的存在。
-
持久性(Durability):一旦事务提交,其结果应该永久保存在数据库中,并且不受任何系统故障的影响。即使系统崩溃或发生故障,事务提交的结果也应该保持不变。
事务是确保数据库操作的一致性和可靠性的重要机制,它提供了一种方式来管理并发访问数据库,确保多个操作之间的一致性和正确性。在数据库系统中,事务通常由事务管理器来管理,并通过事务日志来记录和恢复事务的状态。
2. 分布式事务
分布式事务是指跨多个节点、多个数据存储或多个服务之间进行的事务操作。在分布式系统中,由于数据和服务的分散性,事务操作可能涉及多个资源,因此需要特殊的机制来确保事务的一致性、隔离性、原子性和持久性(ACID 特性)。
2.1 2PC(二阶段提交)
二阶段提交(Two-Phase Commit,2PC)是一种用于分布式事务处理的协议,旨在确保分布式系统中所有参与者要么全部提交事务,要么全部回滚事务,以保证事务的原子性。
2PC 协议包含两个阶段:
-
准备阶段(Prepare Phase):在准备阶段,事务的协调者向所有参与者发送请求,要求它们准备好执行事务操作。参与者执行本地事务,并将事务的执行结果通知协调者。如果所有参与者都成功执行了本地事务,则协调者向所有参与者发送提交请求;否则,如果有任何一个参与者失败或超时,协调者将向所有参与者发送回滚请求。
-
提交阶段(Commit Phase):在提交阶段,协调者根据准备阶段的结果决定是否提交事务。如果所有参与者都成功执行了本地事务,协调者向所有参与者发送提交请求,并要求它们提交事务。参与者收到提交请求后,将执行本地事务提交操作,并通知协调者提交成功;如果有任何一个参与者在准备阶段失败或超时,协调者将向所有参与者发送回滚请求,要求它们回滚事务。
2PC 的同步阻塞协议指的是在执行准备和提交阶段时,协调者和参与者之间采用同步的通信方式,并在等待对方响应时处于阻塞状态。具体来说:
在准备阶段,协调者向所有参与者发送准备请求,并等待所有参与者的响应。只有在收到所有参与者的响应后,协调者才会决定提交或回滚事务,并向所有参与者发送相应的请求。期间,协调者处于阻塞状态,无法处理其他请求。
在提交阶段,协调者向所有参与者发送提交请求,并等待所有参与者的响应。只有在收到所有参与者的提交成功响应后,协调者才会确认事务提交。如果有任何一个参与者未能提交事务,协调者将向所有参与者发送回滚请求。期间,协调者同样处于阻塞状态,无法处理其他请求。
2PC 的同步阻塞协议保证了事务的原子性,但也存在一些问题,如单点故障、阻塞和超时等,因此在实际应用中需要权衡考虑,并结合其他机制来提高系统的性能和可靠性。
2.2 3PC (三阶段提交)
三阶段提交(Three-Phase Commit,3PC)是二阶段提交(2PC)的改进版本,旨在解决 2PC 中的某些问题,如阻塞和单点故障。3PC 引入了一个额外的阶段,在提交阶段之前进行准备,并在准备阶段和提交阶段之间增加了一个超时机制。相比于 2PC,3PC 在一定程度上提高了系统的可用性和性能。
3PC 的三个阶段如下:
-
CanCommit 阶段(准备阶段):协调者向所有参与者发送 CanCommit 请求,询问它们是否可以提交事务。参与者在收到请求后,会检查自己是否可以执行事务,并在准备好后向协调者发送 Ready 或 Abort 响应。如果所有参与者都准备好了,则协调者会向所有参与者发送 DoCommit 请求,否则会向所有参与者发送 DoAbort 请求。
-
PreCommit 阶段(预提交阶段):协调者收到所有参与者的 Ready 响应后,会向所有参与者发送 PreCommit 请求,告知它们即将提交事务。参与者收到 PreCommit 请求后,会进入预提交状态,并在事务提交前执行一些准备工作,如持久化日志。如果有任何一个参与者在超时时间内未响应或者发送了 Abort 响应,则协调者会向所有参与者发送 DoAbort 请求。
-
DoCommit 阶段(提交阶段):在收到所有参与者的 Ack 响应后,协调者会向所有参与者发送 DoCommit 请求,要求它们正式提交事务。参与者收到请求后,会执行事务提交操作,并在提交成功后向协调者发送 Ack 响应。协调者收到所有参与者的 Ack 响应后,确认事务提交,并向所有参与者发送确认消息。如果有任何一个参与者在超时时间内未响应,则协调者会向所有参与者发送 DoAbort 请求。
相比于二阶段提交,三阶段提交引入了额外的预提交阶段,使得参与者在正式提交事务之前能够做一些准备工作,并通过超时机制避免了某些阻塞问题。但是,三阶段提交并不能完全解决分布式系统中的所有问题,如单点故障、网络分区等依然可能存在。
2.3 TCC(补偿事务)
TCC(Try-Confirm-Cancel)是一种分布式事务模式,旨在解决分布式系统中的事务一致性问题。TCC 将整个事务分解为三个阶段,分别是尝试(Try)、确认(Confirm)和取消(Cancel),每个阶段对应着事务的不同状态,以确保事务在出错或者部分执行失败时能够保持一致性。
下面是 TCC 模式的三个阶段:
-
尝试(Try)阶段:在尝试阶段,系统尝试着预留必要的资源,并执行业务逻辑,但并不真正执行数据库的更新操作。在这个阶段,系统会检查各项条件是否满足,包括业务逻辑是否可行,资源是否足够等。如果条件满足,则进入确认阶段;如果条件不满足,则进入取消阶段。
-
确认(Confirm)阶段:在确认阶段,系统将尝试阶段预留的资源真正提交或者释放。在这个阶段,系统会执行数据库的更新操作,将之前预留的资源真正占用或释放。如果操作成功,则事务执行成功,提交完成;如果操作失败,则进入取消阶段。
-
取消(Cancel)阶段:在取消阶段,系统执行尝试阶段中预留的资源的释放操作,回滚之前的操作。在这个阶段,系统会执行数据库的回滚操作,将之前预留的资源释放掉。如果操作成功,则事务执行失败,回滚完成;如果操作失败,则需要人工干预处理。
TCC 模式的优点是可以灵活地控制事务的执行过程,可以在不同的阶段实现业务逻辑的检查、资源的预留、操作的提交或回滚,从而保证事务的一致性。然而,TCC 模式也存在一些挑战,比如实现复杂度高、需要手动编写确认和取消逻辑、容错性差等。因此,在选择使用 TCC 模式时,需要权衡利弊,并根据实际业务场景和需求来决定是否使用。
2.4 MQ(本地消息队列)
本地消息队列(MQ)是一种用于在应用程序内部进行异步通信的机制。它类似于传统的消息队列系统,但是在应用程序内部使用,不涉及网络通信。
在使用本地消息队列时,应用程序内的不同模块可以通过将消息发送到队列中,然后由消费者模块来接收和处理这些消息,实现模块之间的解耦和异步通信。通常,本地消息队列会提供消息的持久化、消息的订阅/发布、消息的重试机制等功能,以保证消息的可靠性和稳定性。
一些常见的本地消息队列包括:
-
RabbitMQ:RabbitMQ 是一个流行的开源消息队列系统,它支持多种消息协议,如 AMQP、STOMP、MQTT 等,提供了丰富的功能和灵活的配置选项。
-
Apache Kafka:Kafka 是一个分布式的高吞吐量消息队列系统,设计用于处理大规模的数据流。它支持消息的持久化和分区,适用于构建实时数据处理系统。
-
ActiveMQ:ActiveMQ 是一个基于 JMS(Java Message Service)规范的消息队列系统,它提供了可靠的消息传递、消息持久化、事务支持等功能。
-
Redis:Redis 是一个开源的内存数据库,它也可以用作消息队列系统。Redis 的 List 数据结构和发布/订阅功能可以用来实现简单的消息队列。
-
RocketMQ:RocketMQ 是阿里巴巴开源的分布式消息队列系统,它具有高可靠性、高吞吐量和低延迟的特点,适用于大规模的分布式系统。
本地消息队列的使用可以帮助应用程序实现解耦、提高系统的可伸缩性和可维护性,同时可以降低系统之间的依赖性,提高系统的稳定性和灵活性。
2.6 Sagas事务模型
Sagas 是一种用于处理分布式事务的模型,它旨在解决微服务架构中的长事务和分布式事务的问题。Sagas 模型将长事务分解为多个小事务,每个小事务都是原子的,并且可以独立执行或者撤销。Sagas 模型通常包括以下几个关键组件:
-
事务管理器(Transaction Manager):负责协调和管理整个 Saga,确保 Saga 中的所有步骤都能够正确执行或者回滚。事务管理器负责启动 Saga、监控 Saga 的执行过程,并在必要时触发回滚操作。
-
Saga 定义(Saga Definition):定义了 Saga 的结构和流程,包括 Saga 中的各个步骤、步骤的执行顺序、步骤之间的依赖关系等。Saga 定义通常以编程方式或者配置文件的形式存在。
-
Saga 实例(Saga Instance):表示 Saga 的一个具体实例,每个 Saga 实例都有一个唯一的标识符,并且记录了 Saga 的执行状态和上下文信息。Saga 实例在执行过程中会不断更新其状态,直到最终完成或者回滚。
-
Saga 步骤(Saga Step):表示 Saga 中的一个小事务,每个步骤都是一个原子操作,可以执行某个业务逻辑或者调用外部服务。Saga 步骤通常包括执行操作、补偿操作以及状态转换等。
-
补偿(Compensation):补偿操作是指在 Saga 执行过程中出现错误或者失败时,用于回滚之前已经执行的步骤并恢复系统到一个一致的状态的操作。每个 Saga 步骤都应该有对应的补偿操作,以保证 Saga 的可靠性和一致性。
Sagas 模型与传统的 ACID 事务模型不同,它更适用于分布式系统和微服务架构中的长事务处理。Sagas 将长事务拆分为多个原子操作,并通过补偿机制来保证事务的最终一致性。这种模型使得系统更加灵活、可伸缩,并且更容易处理分布式环境下的故障和异常情况。
更多推荐


所有评论(0)