【理论篇】分布式事务看这一篇就够了

0. 基础理论

在讲解具体方案之前,我们有必要了解一些分布式事务所涉及到的基础理论知识。

分布式事务是指事务的参与者、支持事务的服务器、资源服务器以及事务管理器分别位于不同的分布式系统的不同节点之上。例如在大型电商系统中,下单接口通常会扣减库存、减去优惠、生成订单 id, 而订单服务与库存、优惠、订单 id 都是不同的服务,下单接口的成功与否,不仅取决于本地的 db 操作,而且依赖第三方系统的结果,这时候分布式事务就保证这些操作要么全部成功,要么全部失败。本质上来说,分布式事务就是为了保证不同数据库的数据一致性。
在这里插入图片描述

一致性原则

  1. 强一致性:是最严格的一种一致性模型,要求在分布式系统中的所有节点,对于同一份数据,无论在任何时候读取,都能得到最新写入的数据。也就是说,当更新操作完成后,任一后续进入系统的读操作都将返回该值。例如,在分布式数据库中,一次写操作完成后,所有的读操作都应返回最新的数据。

  2. 弱一致性:相对于强一致性而言,弱一致性不需要立即在所有节点上看到最新的更新,因此允许存在短暂的数据不一致。只要在没有新的更新操作时,系统最终能保证数据的一致,就满足了弱一致性。弱一致性的优点是提高了系统的并发性能,但是缺点是可能会读取到过期的数据。

  3. 最终一致性:最终一致性是弱一致性的一种特例,它的核心思想是系统会确保在没有后续更新的情况下,最终所有的数据副本都将达到一致的状态。也就是说,在无穷的时间长度后,所有副本都将达到一致。这种一致性模型在没有发生新的更新操作时,系统会逐步试图去修复不一致的副本,直到所有的副本都达到一致为止。例如,DNS系统就是采用的最终一致性模型。

CAP 原则

CAP原则是分布式系统设计的一个基本理论模型,其中的C、A、P分别代表:

  1. C (Consistency): 一致性,所有节点在同一时刻应该看到相同的数据。

  2. A (Availability): 可用性,保证每个请求都能获得响应,不保证每次请求都能获取到最新的数据。

  3. P (Partition tolerance): 分区容忍性,即系统在网络分区(网络断开)的情况下,仍能保证对外提供一致性和可用性。

在这里插入图片描述

CAP原则指出,对于一个分布式系统,不可能同时满足C、A、P三个需求,最多只能满足其中的两项。这三项特性的互斥性,构成了设计和选择分布式系统的一个基本的权衡框架。例如,若设计一个同时满足一致性和可用性的系统,那么在遇到分区容错时,可能会导致部分节点不可用,因此无法满足分区容错性。

柔性事务

柔性事务是一种相比于传统事务(ACID事务)更加灵活的事务处理机制。ACID事务模型在一些分布式系统或大数据应用中,可能无法很好地满足需求,因为它需要在一个操作序列中的所有操作都成功才能提交事务,这在大规模和分布式环境中可能难以实现。柔性事务通过降低一致性和隔离性的要求,提高了可用性和性能。

实际应用中的柔性事务往往采用BASE(Basically Available, Soft State, Eventually Consistent)理论,也就是基本可用、软状态、最终一致性。在这个模型中,系统允许在一段时间内数据的不一致,只要保证最终数据能够达到一致状态。

例如,电商平台中的秒杀活动,如果使用传统的ACID事务处理模型,可能会因为并发量大导致系统崩溃。如果采用柔性事务,系统在用户下单后,可以先返回下单成功的信息,而库存的扣减可以稍后再处理。这样,即使在大量并发的情况下,系统也能保持基本的可用性,而库存的一致性可以在稍后通过后台进程来保证。

BASE 理论

BASE理论是为了解决CAP原则中无法同时满足三个特性的问题而提出的一种理论模型。BASE是Basically Available(基本可用)、Soft state(软状态)、Eventually consistent(最终一致性)三个短语的首字母缩写。

  1. Basically Available(基本可用):系统在出现故障时,允许损失部分可用性,但不会出现系统完全不可用。例如,响应时间可能会变慢,或者部分功能可能无法使用,但绝不会出现整个系统崩溃的情况。

  2. Soft state(软状态):系统的状态可以有一段时间的不一致,或者系统可以处于中间状态,而这个中间状态可以用于系统的可用性和一致性。

  3. Eventually consistent(最终一致性):系统保证在没有新的数据更新的情况下,经过一段时间后,数据最终能够达到一致的状态。在此期间,系统的所有数据副本可能会出现短暂的不一致。

BASE理论的实质是为了解决关系型数据库强一致性引起的问题,而采用最终一致性,通过牺牲实时性来获得系统的高可用性。这种理论适用于对数据一致性要求不是非常严格的系统,例如电商网站的商品库存等。

幂等操作

幂等操作指的是一个操作无论执行多少次,结果始终都是一样的。这种概念在计算机科学、分布式系统和网络协议等领域中非常重要。

例如,一个删除文件的操作就是幂等的,因为无论你执行多少次删除操作,该文件始终都会被删除,结果始终一样。同样,HTTP的GET方法也是幂等的,因为无论你获取多少次,服务器返回的资源状态始终是一样的。

需要注意的是,幂等性并不意味着操作没有任何效果。比如上述的删除文件操作,它的结果是文件被删除,这个结果是有实际效果的。幂等性强调的是无论操作执行多少次,其结果都是一样的。

1. 基本介绍

1.1. 分布式事务的定义

在这里插入图片描述
分布式事务是指在分布式系统中,涉及到两个及以上的节点协同完成的事务。由于这些节点可能在物理上分布于不同的机器,甚至在云上,因此需要在所有相关节点间进行协调和通信,以保证事务的正确执行。在分布式事务中,所有的操作要么全部成功,要么全部失败,这是分布式事务的原子性。

1.2. 分布式事务使用场景

分布式事务广泛应用于各种需要跨系统或跨数据库操作的场景,如电商、金融、物流等。例如在线购物中,用户下单、支付、仓库发货、物流配送等环节可能涉及到不同的系统,只有所有环节都成功,整个订单才能完成。

分布式事务的重要性主要体现在其保证数据一致性的能力。在分布式环境中,各个节点的状态需要保持一致,否则可能会导致数据不一致、业务逻辑出错等问题。分布式事务通过事务的一致性和原子性保证了在不同节点间的操作能够达到一致的效果。

在现代的互联网应用中,分布式事务在很多场景下都有应用,下面是两个具体的例子:
在这里插入图片描述

  1. 电商购物流程,在电商平台中,用户的购物操作可能涉及到库存系统、订单系统、支付系统等多个系统。这些系统可能部署在不同的服务器上,形成一个分布式的环境。在这种情况下,如果用户下单购买了一个商品,那么这个操作就需要在库存系统中减少商品数量,在订单系统中创建新的订单,在支付系统中进行支付操作。这三个操作需要组成一个分布式事务,要么全部成功,要么全部失败。否则,就可能出现数据不一致的情况,比如库存减少了,但是订单没有创建成功,或者订单创建成功了,但是支付失败了。

  2. 银行转账操作,银行的转账操作通常涉及到两个账户,一个是付款账户,一个是收款账户。这两个账户可能在不同的数据库或者服务器上。转账操作需要在付款账户上减少相应的金额,在收款账户上增加相应的金额。这两个操作需要组成一个分布式事务,要么全部成功,要么全部失败。否则,就可能出现数据不一致的情况,比如付款账户的金额减少了,但是收款账户的金额没有增加。

2. 分布式事务工作原理

分布式事务实现主流的实现方案中一般需要以下几个主体,但是这个不是标准,在一些简化的分布式事务实现中,事务参与者和资源管理器可能合并为一个主体。比如在微服务架构下的Saga事务模式,服务本身就是事务的参与者,同时也管理着自己的数据库资源。也就是说,服务本身既是事务参与者,又是资源管理器
在Saga事务模式下,每个服务执行本地事务,并发布事件给其他服务。如果某个服务的本地事务失败,那么该服务会发布一个补偿事件,用于补偿之前已经执行成功的所有事务。这种模式下,事务参与者和资源管理器合并为一个主体,由服务本身来完成。
我们分别介绍一下分布式事务中的几个主体的职责

  1. 事务协调者(Transaction Coordinator):事务协调者负责协调和管理分布式事务的执行。它主要负责事务的开始、提交和终止。

  2. 事务参与者(Transaction Participants):事务参与者执行分布式事务的实际操作。他们在分布式事务中执行它们自己的本地事务,并根据事务协调者的指示决定提交或回滚事务。

  3. 资源管理器(Resource Manager):资源管理器负责管理和控制分布式事务访问和操作的资源,如数据库、消息队列等。

  4. 通信系统(Communication System):通信系统负责协调者和参与者之间的通信,包括请求发送和响应接收。

  5. 日志系统(Log System):日志系统用于记录分布式事务的操作过程,包括事务开始、结束、提交和回滚等信息,为故障恢复和事务一致性提供支持。

  6. 锁管理器(Lock Manager):锁管理器负责在分布式环境中管理并控制对资源的并发访问,以保证数据的一致性和事务的隔离性。

除了解决事务提交和回滚的问题外,分布式事务的实现过程还必须要考虑以下两个问题

  1. 并发控制

并发控制主要用于解决并发操作可能导致的数据不一致问题。通常的方法有两种:一种是基于锁的方法,例如排他锁、共享锁等;另一种是基于时间戳的方法,通过为每个事务分配一个全局唯一的时间戳,来确定事务之间的执行顺序。

  1. 死锁处理

在分布式系统中,死锁问题更为复杂。死锁检测通常有两种方法:一种是基于超时的方法,如果一个事务长时间无法获取到锁,则认为发生了死锁;另一种是基于图的方法,将事务及其请求的资源视为图中的节点和边,通过检测图中是否存在环来判断是否存在死锁。死锁解除通常采用的方法是中止或回滚一部分事务,以释放被锁住的资源。选择哪些事务进行中止或回滚,通常有几种策略,如优先中止运行时间最长或最短的事务,优先中止修改数据量最大或最小的事务,优先中止优先级最低的事务等。

3. 分布式事务协议

3.1. 两阶段提交协议(2PC)

两阶段提交协议是一种经典的分布式事务提交协议。它分为两个阶段:准备阶段和提交阶段。在准备阶段,协调者询问所有参与者是否准备好提交事务;在提交阶段,如果所有参与者都表示准备好了,那么协调者就会通知他们提交事务,否则通知他们终止事务。
在这里插入图片描述
在这里插入图片描述

3.2. 三阶段提交协议(3PC)

三阶段提交协议是改进版的两阶段提交协议,为了解决两阶段提交协议中的阻塞问题。除了两阶段提交协议中的准备阶段和提交阶段,还增加了一个预提交阶段。在预提交阶段,协调者询问全部的参与者是否可以提交,只有当所有的参与者都同意提交,才进入准备阶段和提交阶段。

3.3. Paxos协议

Paxos协议主要用来解决分布式系统中的共识问题,即在一个由多个节点构成的系统中,如何让这些节点对一个值达成一致。Paxos协议被广泛应用在许多分布式系统和数据库中。
使用PolarDB举例。通过引入中心授时服务(TSO),结合多版本并发控制(MVCC),确保读取到一致的快照,而不会读到事务的中间状态。如下图所示,提交事务时,计算节点(CN)执行事务时从TSO获取到时间戳,随着数据一同提交到存储节点(DN)多版本存储引擎上,CN通过读取快照时间戳去DN上读取相应版本的数据
在这里插入图片描述

3.4. Raft协议

是基于 Raft 协议来实现事务一致性的。Raft协议是为了解决分布式系统中的共识问题,它是Paxos协议的一种更易理解和实现的替代方案。Raft协议通过选举的方式选择一个领导者,由领导者来决定和维护系统的状态。具体实现其实我也知识大概了解,此处就不讲了,我们只说下哪些数据库使用raft协议来实现分布式的一致性。
有许多分布式系统是基于 Raft 协议来实现事务一致性的

  1. TiDB: 前段时间比较火的TiDB 是由PingCAP 开发的分布式 SQL 数据库。其分布式事务模型基于 Google 的 Percolator 模型,并采用 Raft 协议进行数据复制。

  2. CockroachDB: 高度易扩展的,支持事务的分布式 SQL 数据库,它使用 Raft 协议来保证分布式一致性。

4. 分布式事务实现技术

4.1. XA接口

XA接口是一个由X/Open公司提出的分布式事务标准接口,主要定义了在两阶段提交协议中协调者和参与者的交互接口。在分布式系统中,如果一个事务需要跨多个资源(如数据库、消息队列等)进行操作,那么可以通过XA接口来协调这些资源,实现分布式事务。
在这里插入图片描述

4.2. TCC(Try-Confirm-Cancel)

TCC是一种应用层面的分布式事务解决方案,它分为Try阶段、Confirm阶段和Cancel阶段。在Try阶段,尝试执行事务,若所有参与者都成功,进入Confirm阶段;Confirm阶段,确认执行事务,若所有参与者都确认,事务成功;否则,进入Cancel阶段,取消事务操作,回滚已经执行的操作。
在这里插入图片描述

4.3. Saga

Saga是指一种长寿命的事务,它由一系列的子事务构成,每个子事务都可以独立地提交。如果在Saga事务中的某个阶段失败,那么将由补偿交易反向地执行之前的子事务,以此来回滚整个Saga事务。

在这里插入图片描述
在Saga模式中,一个分布式事务被分解为一系列的子事务,每个子事务都可以独立地成功或失败。Saga保证:如果所有子事务都成功,那么整个事务就成功;如果有任意一个子事务失败,那么Saga就启动一系列补偿操作(compensating transactions)来撤销已经成功的子事务,以此达到整个事务的最终一致性。

Saga分布式事务模型是在无法保证分布式系统中的所有参与者都能同时提交或回滚的情况下,提供一种新的解决方案。它适用于长时间运行的事务处理,并且允许各参与者在事务处理过程中释放资源,从而避免长时间锁定资源。

Saga分布式事务的核心思想是将一个大的事务分解为一系列的小事务(本地ACID事务),并且为每个小事务都提供一个与之对应的补偿事务,当某个小事务失败时,就执行所有已经成功的小事务对应的补偿事务,以此来实现分布式系统中事务的最终一致性。

Saga分布式事务模型在微服务架构中应用较为广泛,因为在微服务架构中,每个服务都可能部署在不同的服务器上,且每个服务都有自己独立的数据库,这就使得在微服务架构中实现分布式事务变得尤为困难。而Saga分布式事务模型提供了一种有效的解决方案。

在Saga事务模型中,我们使用Java伪代码写个示例理解一下
executeSaga() 方法分别执行了 placeOrder(), deductPayment(), issuePoints() 这三个子事务,如果在执行过程中有任何一个子事务发生异常,就会执行对应的回滚逻辑,保证整个流程的一致性。

public class OrderProcessingSaga {
    
    

    // 下单子事务
    public void placeOrder() {
    
    
        try {
    
    
            // 执行下订单操作的逻辑
        } catch (Exception e) {
    
    
            // 如果下订单操作失败,回滚之前的操作
            rollbackPlaceOrder();
            throw e;
        }
    }

    // 扣款子事务
    public void deductPayment() {
    
    
        try {
    
    
            // 执行扣款操作的逻辑
        } catch (Exception e) {
    
    
            // 如果扣款操作失败, 回滚之前的操作
            rollbackDeductPayment();
            throw e;
        }
    }

    // 发放积分子事务
    public void issuePoints() {
    
    
        try {
    
    
            // 执行发放积分操作的逻辑
        } catch (Exception e) {
    
    
            // 如果发放积分操作失败,回滚之前的操作
            rollbackIssuePoints();
            throw e;
        }
    }

    // 下订单操作的回滚逻辑
    public void rollbackPlaceOrder() {
    
    
        // 执行下订单操作的回滚逻辑
    }

    // 扣款操作的回滚逻辑
    public void rollbackDeductPayment() {
    
    
        // 执行扣款操作的回滚逻辑
    }

    // 发放积分操作的回滚逻辑
    public void rollbackIssuePoints() {
    
    
        // 执行发放积分操作的回滚逻辑
    }

    // Saga事务执行方法
    public void executeSaga() {
    
    
        placeOrder();
        deductPayment();
        issuePoints();
    }
}

4.4. 柔性事务

柔性事务模型以 BASE (Basically Available, Soft state, Eventually consistent) 区别于传统的分布式事务模型 ACID,只请求在结算阶段达成最终一致,还可以根据业务需求进行定制化最终一致方案,适应各种业务场景,如最大努力通知型、TCC型、可补偿型和异步确保型等。
最大努力通知
最大努力通知最常见的场景就是支付回调,支付服务收到第三方服务支付成功通知后,先更新自己库中订单支付状态,然后同步通知订单服务支付成功。如果此次同步通知失败,会通过异步脚步不断重试地调用订单服务的接口。
在这里插入图片描述

5. 分布式事务的实际应用

5.1. 电商系统

在电商系统中,用户下单购买商品这一行为涉及到库存管理,订单管理,支付系统等多个子系统。例如,用户下单后,需要从库存中扣除相应的商品数量,生成订单,并在支付系统中生成支付记录。这些子系统可能分布在不同的服务器上,操作它们就需要用到分布式事务,以保证在出现异常情况时,如用户取消订单,可以做到数据的一致性,将库存数量回滚,删除订单和支付记录。

5.2. 财务(支付)系统

在财务系统中,涉及到多个账户之间的资金转移。例如,一笔转账操作,需要从一个账户扣款,并在另一个账户加款。这两个操作需要在不同的数据库中进行,而且必须保证两个操作要么都成功,要么都失败,以保证资金的一致性。这就需要用到分布式事务。

5.3. 物流系统

在物流系统中,包含了订单管理,库存管理,配送管理等多个子系统。例如,当一个订单从下单到发货,需要经过库存扣减,订单生成,配送信息生成等多个步骤,这些步骤可能分布在不同的服务器上,需要用到分布式事务来保证数据的一致性。

6. 参考文档

  1. 分布式事务介绍 https://zhangxiongbiao.com/post/2019-08-25/%E5%88%86%E5%B8%83%E5%BC%8F%E4%BA%8B%E5%8A%A1.html

  2. 分布式事务 http://www.cnblogs.com/savorboard/p/distributed-system-transaction-consistency.html

猜你喜欢

转载自blog.csdn.net/wangshuai6707/article/details/132867031
今日推荐