文章目录
- 一. 什么是分布式事务?
- 二. 分布式事务的挑战
- 三. 事务的ACID特性
- 四. CAP理论与BASE理论
- 1. CAP理论
- 1.1. 三大特性
- 1.2. 三者不能兼得
- 2. BASE理论
- 五. 分布式事务解决方案
- 1. 两阶段提交(2PC)
- 2. TCC(Try-Confirm-Cancel)
- 六. 小结
之前我们了解分布式系统中的互斥问题及其解决方案(分布式锁)。互斥问题讨论的是多个进程对同一个临界资源进行操作的问题,而本文将要讨论的是同一个进程对多个临界资源进行操作的问题。
一. 什么是分布式事务?
简单来说,分布式事务就是跨多个独立的资源(比如数据库)进行的事务。
举个例子,假设一个银行系统需要处理一次转账操作:从A账户转出100元分别到B账户30元、C账户70元。这种操作不仅仅涉及到一个数据库,而是涉及多个资源(A账户、B账户、C账户)。这个转账操作要么完全成功,所有的账户变动都要完成;要么完全失败,没有任何账户被修改。类似这样的跨多个资源的事务,我们称之为分布式事务。
二. 分布式事务的挑战
在分布式系统中,跨多个服务和数据库执行的事务面临以下几个挑战:
- 一致性问题:如何保证数据在多个系统中保持一致?
- 网络故障:网络不稳定可能导致事务执行失败,如何保证事务不会中途丢失或被错误提交?
- 并发冲突:多个服务之间并发执行的事务如何互不干扰?
为了处理这些挑战,分布式事务采用了不同的理论和技术框架来确保数据一致性、可用性和事务的正确性。
三. 事务的ACID特性
分布式事务的核心目标是保证事务的一致性和完整性,这与单体应用中的ACID特性密切相关。ACID是事务管理的基本要求,包含以下四个特性:
- 原子性(Atomicity):事务中的所有操作要么全部成功,要么全部失败,不能部分成功。
- 一致性(Consistency):事务执行前后的数据一致,系统从一个一致性状态转变到另一个一致性状态。比如:从 A 账户转出 100元,B 账户中到账 30 元,C 账户中到账 70 元。完成这个事务操作以后,A 账户减少的钱数与 B、C 账户增加的钱数总和应该是一样的,都是 100 元。
- 隔离性(Isolation):并发执行的事务互不干扰,每个事务对外界是隔离的。
- 持久性(Durability):一旦事务提交,数据更改就会永久保存,即使系统崩溃也不丢失。
在单体架构中,ACID特性易于实现,但在分布式系统中,由于网络延迟、节点故障等问题,保证强一致性变得困难。此时,我们需要更灵活的解决方案。
四. CAP理论与BASE理论
1. CAP理论
1.1. 三大特性
在分布式系统中,由于网络和硬件的限制,无法同时保证一致性、可用性和分区容错性,这就是著名的CAP理论的核心思想。CAP理论提出,在一个分布式系统中,最多只能保证以下两个特性:
-
一致性(Consistency):所有节点的视图是相同的,保证每个节点的数据在同一时刻一致。
-
可用性(Availability):可用性是指在分布式系统中,即使一部分节点出现故障,系统仍然可以响应用户的请求。
- 分区容错性(Partition tolerance):假设两个数据库节点(每个节点数据一致)分布在两个区,而这两个区的通信发生了问题,因此无法达成数据一致,这就是分区问题,此时需要从一致性和可用性之间做出选择。是选择一致性(C),等待两个区的数据同步了再去获取数据,还是选择可用性(A),只获取其中一个区的数据?
1.2. 三者不能兼得
CAP理论表明,当网络分区发生时,分布式系统必须在一致性和可用性之间做出选择。如下例子:
业务代码对两个节点的通信失败,往数据库 01 写入记录 A 时,需要锁住数据库02 中的记录 A,不让其他业务代码修改此纪录,直到数据库 01 修改完成。一致性和可用性在此刻是矛盾的,不能兼得。
保证特性 | 放弃特性 | 适用场景 | 说明 |
---|---|---|---|
一致性、可用性 | 分区容错性 | 不适用(无法实现) | 如果放弃分区容错性,就等于放弃使用分布式系统,即单体。 |
一致性、分区容错性 | 可用性 | 金融领域(如银行、支付系统等) | 需要保证数据一致性,甚至在网络分区时也要牺牲系统可用性,保证交易数据的正确性和一致性。 |
可用性、分区容错性 | 一致性 | ToC端应用(如电商网站、社交平台等) | 强调用户体验,牺牲部分一致性以换取系统高可用性,允许数据暂时不一致。适合大流量和高并发的应用场景。 |
2. BASE理论
由于 CAP 理论导致一个应用同时至多只能支持两个特性,无法三全其美,且高并发系统追求的往往是可用性,因此对 CAP 理论进行进一步扩充,产生了 BASE 理论。
特性 | 说明 | 举例 |
---|---|---|
基本可用性 | 系统能够在流量激增或节点故障时,通过限流或降级保证用户请求可用。 | 电商系统在流量激增时,优先保证核心业务(如订单处理),将非核心业务降级处理。 |
软状态 | 数据副本之间允许存在短时间的数据不一致,容忍数据同步延迟。 | 数据库01中记录A写入后,数据库02中的记录B会在一定延迟后同步,而不是立即同步。 |
最终一致性 | 数据在短时间内可能不一致,但过了一段时间后,数据会最终达到一致。 | 在分布式系统中,数据副本可能会在网络延迟时出现不一致,但经过一段时间,数据会同步一致。 |
BASE理论强调的是最终一致性,而不是传统数据库中的强一致性。它适用于那些需要高可用性和容忍短期不一致的系统,例如电商平台和社交网络。
五. 分布式事务解决方案
为了在分布式系统中保证事务的正确性,业界提出了多种分布式事务解决方案,常见的有两阶段提交(2PC) 和 TCC(Try、Confirm、Cancel)。
1. 两阶段提交(2PC)
**两阶段提交协议(2PC)的基本思想是通过协调者(Transaction Manager)和参与者(Resource Manager)来控制事务的提交或回滚。2PC的工作过程分为两个阶段:
准备阶段:
事务协调者(事务管理器)询问每个参与者是否准备好,马上要执行事务了。事务参与者会根据自身业务和资源情况进行检查,然后给出反馈。
检查过程根据业务内容的不同而不同,例如订票业务需要检查是否有剩余票、扣款业务需要检查余额是否足够。只有检查通过,才能返回就绪(ready)信息。否则,事务将终止,并且等待下次询问。由于检查过程需要完成一些操作,因此需要写 redo 日志和 undo 日志,以便事务失败重试,或者失败回滚时使用。
提交阶段:
如下图:如果事务协调者接收到事务参与者检查失败或者超时的消息,会给其发送回滚(rollback)消息,否则发送提交(commit)消息。
以下是整理后的两种情况的处理过程:
情况 | 步骤 |
---|---|
情况 1:事务回滚 | 条件:只要有一个事务参与者反馈未就绪(no ready),事务协调者会回滚事务。 |
1. 事务协调者向所有事务参与者发出回滚请求。 | |
2. 事务参与者使用第一阶段的 undo 日志信息执行回滚操作,并释放事务期间占用的资源。 | |
3. 各事务参与者向事务协调者反馈应答(ack)消息,表示完成回滚操作。 | |
4. 事务协调者接收到所有事务参与者的应答消息,即完成事务回滚。 | |
情况 2:事务提交 | 条件:当所有事务参与者均反馈就绪(ready)消息时,事务协调者会提交事务。 |
1. 事务协调者向所有事务参与者发出正式提交事务的请求。 | |
2. 事务参与者执行提交(commit)操作,并释放事务期间占用的资源。 | |
3. 各事务参与者向事务协调者反馈应答(ack)消息,表示完成提交操作。 | |
4. 事务协调者接收到所有事务参与者的应答(ack)消息,即完成事务提交。 |
尽管2PC简单易理解,但它存在问题,比如在网络分区或故障情况下,可能会导致事务挂起,无法继续提交或回滚,造成数据不一致。
2. TCC(Try-Confirm-Cancel)
TCC(Try-Confirm-Cancel)的核心思想是对于每个资源的原子操作,应用程序都需要注册一个与此操作对应的确认操作和补偿(撤销)操作。其中确认操作负责在原子操作执行成功时进行事务提交,补偿操作负责在原子操作执行失败时对事务进行回滚。
TCC协议分为三个阶段:
- Try阶段:进行资源的预检查和预留,确保资源可用。
- Confirm阶段:负责对业务系统做确认提交。如果 Try 阶段执行成功,表明针对资源的操作已经准备就绪,此时执行 Confirm 便会提交对资源的操作。也就是说当资源准备好时,只用提交该操作执行就好了。
- Cancel阶段:负责在业务执行错误,需要回滚时执行业务取消操作,此时就需要释放 Try 阶段预留的资源了。换句话说,是在资源操作执行失败的情况下,根据之前预留的资源情况进行回滚。
TCC协议通过提供灵活的补偿机制,能够在事务失败时进行回滚,保证系统的一致性。
例子:
假设有一个转账服务,需要把 A 银行中 A 账户的 100 元分别转到 B 银行的 B 账户和 C 银行的 C 账户,这三个银行的转账服务各不相同,因此这次转账服务就形成了一次分布式事务。
阶段 | 操作描述 | 具体步骤 |
---|---|---|
Try 阶段 | 检测资源是否可用,验证所有参与者的资源可用性,并记录相关信息。 | 1. 检查 A 账户余额是否大于 100 元。 2.记录 A 账户的总金额、转出金额。 3. 记录 B、C 账户的总金额、转入金额。 4. 在数据库中保存相关字段(如余额、转出金额)。 5. 如果资源可用,进入 Confirm 阶段;如果不可用,回滚。 |
Confirm 阶段 | 执行具体的转账逻辑,进行资源更新,并设置事务的成功状态。 | 1. 从 A 账户扣除 100 元,更新余额为 220 - 100 = 120 。2. 更新 B 账户余额为 50 + 30 = 80 ,C 账户余额为 60 + 70 = 130 。3. 更新交易状态为转账成功。 4. 向所有参与者发出确认提交请求,确认各方操作。 |
Cancel 阶段 | 回滚操作,恢复资源到原始状态。 | 1. 如果 Try 阶段失败或资源无法提供,回滚所有操作。 2. A 账户恢复扣除的 100 元,余额为 120 + 100 = 220 。 3. B 账户和 C 账户分别恢复相应的金额,B 账户恢复为 80 - 30 = 50 ,C 账户恢复为 130 - 70 = 60 。 4. 事务回滚并释放占用的资源。 |
六. 小结
分布式事务的出现带来了很多挑战,但也推动了事务管理理论和实践的不断发展。从ACID特性到CAP理论、BASE理论,再到DTP、2PC和TCC等分布式事务协议,每一种理论和方案都在不同的应用场景中发挥着重要作用。
在实际开发中,选择哪种分布式事务方案应根据业务需求、系统架构、性能要求等因素来决定。对于高一致性要求的金融类系统,2PC可能更合适;而对于电商类高并发系统,TCC和BASE理论的结合则能提供更高的可用性和灵活性。