【系统架构】事务处理

系列文章目录

第一章 系统架构的演进
第二章 REST风格架构
第三章 事务处理



前言

事务问题是绝大多数系统所必须考虑的问题,尤其是分布式系统的事务问题。现如今的解决方案都不能很完美的解决这个问题,解决方案通常都比较复杂。事务最终需要解决的问题是实现数据状态的一致性,即符合数据变化后的预期结果。

  • 原子性(Atomic):在同一项业务处理过程中,事务保证了对多个数据的修改,要么同时成功,要么同时被撤销。

  • 隔离性(Isolation):在不同的业务处理过程中,事务保证了各自业务正在读、写的数据互相独立,不会彼此影响。

  • 持久性(Durability):事务应当保证所有成功被提交的数据修改都能够正确地被持久化,不丢失数据。

由以上的三个特性A(原子性)I(隔离性)D(持久性)来实现C(一致性)
事务的概念一开始来源于数据库,但是现如今已经不局限于数据库了,许多需要保持数据一致性的场景都会涉及到事务。包括但不限于数据库、事务内存、缓存、消息队列、分布式存储,等等。

  • 内部一致性:当一个服务只使用一个数据源时,通过 A、I、D 来获得一致性是最经典的做法,也是相对容易的。此时,多个并发事务所读写的数据能够被数据源感知是否存在冲突,并发事务的读写在时间线上的最终顺序是由数据源来确定的,这种事务间一致性被称为“内部一致性”。

  • 外部一致性:当一个服务使用到多个不同的数据源,甚至多个不同服务同时涉及多个不同的数据源时,问题就变得相对困难了许多。此时,并发执行甚至是先后执行的多个事务,在时间线上的顺序并不由任何一个数据源来决定,这种涉及多个数据源的事务间一致性被称为“外部一致性”。


一、局部事务

本地事务是最基础的一种事务解决方案,只适用于单个服务使用单个数据源的场景。从应用角度看,它是直接依赖于数据源本身提供的事务能力来工作的,在程序代码层面,最多只能对事务接口做一层标准化的包装(如 JDBC 接口),并不能深入参与到事务的运作过程当中,事务的开启、终止、提交、回滚、嵌套、设置隔离级别,乃至与应用代码贴近的事务传播方式,全部都要依赖底层数据源的支持才能工作。

原子性和持久性实现

考虑一个购物场景的业务逻辑:在用户账户中减去货款、在商家账户中增加货款、在商品仓库中标记商品为配送状态。一共有三个数据修改操作,操作会有中间状态,则可能出现下面的两种情形:

  • 未提交事务,写入后崩溃:程序还没修改完三个数据,但数据库已经将其中一个或两个数据的变动写入磁盘,此时出现崩溃,一旦重启之后,数据库必须要有办法得知崩溃前发生过一次不完整的购物操作,将已经修改过的数据从磁盘中恢复成没有改过的样子,以保证原子性。

  • 已提交事务,写入前崩溃:程序已经修改完三个数据,但数据库还未将全部三个数据的变动都写入到磁盘,此时出现崩溃,一旦重启之后,数据库必须要有办法得知崩溃前发生过一次完整的购物操作,将还没来得及写入磁盘的那部分数据重新写入,以保证持久性。

原子性实现

  • 事务边界定义: 事务开始于BEGIN TRANSACTION(或类似命令),结束于COMMIT或ROLLBACK。这期间的所有操作被视为一个整体,不可分割。

  • 日志记录: 在事务执行过程中,数据库系统会记录详细的日志信息,包括每个操作的前置状态和后置状态。这些日志是实现原子性的基础。

  • 两阶段提交(2PC): 对于分布式事务,两阶段提交协议确保所有参与节点达成一致,决定是提交还是回滚整个事务。第一阶段为预提交,所有参与者准备提交但不实际执行;第二阶段,如果所有参与者都准备好,则正式提交,否则所有参与者回滚。

  • 事务管理器: 在数据库内部,事务管理器负责监控事务的状态,确保事务的原子性。一旦检测到事务需要回滚(比如遇到错误),它会利用日志信息撤销所有已完成的操作。

持久性实现

  • 预写日志(Write-Ahead Log, WAL): 在数据实际修改之前,先将修改操作记录到日志中。即使系统崩溃,也能根据日志恢复数据到最新状态,确保已提交事务的更改不会丢失。

  • Redo Log: 重做日志记录了事务对数据库所做的修改操作,用于系统恢复时重做这些操作,保证已提交事务的持久性

  • Checkpointing: 定期创建检查点,将当前数据库状态的某一快照记录下来,并同步日志到持久存储。这样在系统恢复时,可以从最近的检查点开始重放日志,大大减少了恢复时间。

  • 事务提交协议: 在事务提交时,只有当相关日志信息被安全地写入到非易失性存储器后,事务才被认为是真正提交的。这确保了即使系统发生故障,事务的结果也是持久的。

隔离性实现

并发情形下实现数据的串行访问,实现方式是加锁同步,现代数据提供了下面的三种锁:

  1. 写锁:如果数据有加写锁,就只有持有写锁的事务才能对数据进行写入操作,数据加持着写锁时,其他事务不能写入数据,也不能施加读锁。

  2. 读锁:多个事务可以对同一个数据添加多个读锁,数据被加上读锁后就不能再被加上写锁,所以其他事务不能对该数据进行写入,但仍然可以读取。对于持有读锁的事务,如果该数据只有它自己一个事务加了读锁,允许直接将其升级为写锁,然后写入数据。

  3. 范围锁:对于某个范围直接加排他锁,在这个范围内的数据不能被写入

    SELECT * FROM books WHERE price < 100 FOR UPDATE;
    

    注意“范围不能被写入”与“一批数据不能被写入”的差别,即不要把范围锁理解成一组排他锁的集合。

二、全局事务

  • 两阶段提交(2PC, Two-Phase Commit):
    这是最经典的实现全局事务的协议之一。2PC分为两个阶段:准备阶段和提交阶段。在准备阶段,事务协调者询问所有参与者是否准备好提交事务;在提交阶段,根据第一阶段的反馈,协调者决定并通知所有参与者是否真正提交或回滚事务。

  • 三阶段提交(3PC, Three-Phase Commit):
    为了解决2PC中协调者失败可能导致的问题,引入了3PC。它在2PC的基础上增加了预提交阶段,以减少阻塞并提高容错性。

  • Saga事务模型:
    Saga通过一系列的本地事务来模拟一个全局事务,每个步骤都尝试向前进,如果某个步骤失败,则执行补偿操作回滚到前一个一致状态。这种模型更适合长活事务和异步通信场景。
    分布式事务协调器(DTC, Distributed Transaction Coordinator):
    如微服务架构中的服务网格(如Istio)或特定中间件(如Seata、LRA)提供的事务协调服务,它们负责管理和协调跨服务的事务,确保数据一致性。

  • 最终一致性:
    在某些分布式系统设计中,为了提高性能和可用性,可能会牺牲即时一致性,采用最终一致性模型。这意味着系统保证在一段时间后达到数据一致,而不是立即一致。

  • CAP定理与BASE理论:
    全局事务设计往往需要权衡CAP定理(Consistency, Availability, Partition tolerance)中的三个要素。BASE理论(Basically Available, Soft state, Eventually consistent)是针对大规模分布式系统提出的一种思想,强调可用性和最终一致性。

三、共享事务

这里的共享事务(Share Transaction)是指多个服务共用同一个数据源,数据源是指提供数据的逻辑设备,不必与物理设备一一对应。

微服务中的共享事务

在微服务架构中,一个业务操作可能需要调用多个服务来共同完成,这就涉及到了跨服务的事务处理问题。传统的ACID事务无法直接应用于分布式环境,因为它们要求事务的所有操作都在同一数据库连接中完成。因此,“共享事务”在这里更多指的是如何在分布式系统中模拟单体应用中的事务效果,确保多个服务之间的操作要么全部成功,要么全部失败。

数据库层面的共享事务

在某些数据库访问框架中,如Entity Framework (EF)中提到的“EF Core上下文共享事务”,是指在应用程序内部,不同的数据库上下文对象可以共享同一个数据库连接来执行操作,从而使得这些操作能够在一个数据库事务的范围内执行,保证数据操作的原子性。

四、分布式事务

CAP定理

CAP 定理(Consistency、Availability、Partition Tolerance Theorem),也称为 Brewer 定理,起源于在 2000 年 7 月,是加州大学伯克利分校的 Eric Brewer 教授于“ACM 分布式计算原理研讨会(PODC)”上提出的一个猜想。

  • 一致性(Consistency):代表数据在任何时刻、任何分布式节点中所看到的都是符合预期的。一致性在分布式研究中是有严肃定义、有多种细分类型的概念,以后讨论分布式共识算法时,我们还会再提到一致性,那种面向副本复制的一致性与这里面向数据库状态的一致性严格来说并不完全等同,具体差别我们将在后续分布式共识算法中再作探讨。

  • 可用性(Availability):代表系统不间断地提供服务的能力,理解可用性要先理解与其密切相关两个指标:可靠性(Reliability)和可维护性(Serviceability)。可靠性使用平均无故障时间(Mean Time Between Failure,MTBF)来度量;可维护性使用平均可修复时间(Mean Time To Repair,MTTR)来度量。可用性衡量系统可以正常使用的时间与总时间之比,其表征为:A=MTBF/(MTBF+MTTR),即可用性是由可靠性和可维护性计算得出的比例值,譬如 99.9999%可用,即代表平均年故障修复时间为 32 秒。

  • 分区容忍性(Partition Tolerance):代表分布式环境中部分节点因网络原因而彼此失联后,即与其他节点形成“网络分区”时,系统仍能正确地提供服务的能力。

CAP为什么只能满足其中两项?

根本原因在于分区容错性是必须要保证的。在实际的分布式系统中,网络分区是一个不可避免的现象。一旦发生分区,系统就面临着在一致性和可用性之间做出选择的问题。

  • 如果系统选择保证一致性和分区容错性,那么就必须牺牲可用性。因为在发生分区时,为了保证数据一致性,部分节点可能需要等待与其他节点通信同步数据,这期间无法响应客户端的请求。

  • 如果系统选择保证可用性和分区容错性,那么就必须牺牲一致性。这意味着在分区期间,不同的节点可能会返回不同版本的数据,直到分区恢复并进行数据同步。

可靠事件队列

可靠事件队列是一种确保消息不会丢失并且能够按照预期被处理的事件队列实现方式。简单来说就是类似于 "开弓没有回头箭"的道理,一旦一个服务事件开始第一步后,后续的应答操作如果因为服务故障或者网络原因没有及时应答,则会持续重试,知道网络或服务恢复。

TCC 事务

TCC事务(Try-Confirm-Cancel)是一种分布式事务处理模式,特别适用于微服务架构和SOA环境中,它通过业务逻辑的三个操作阶段来达到最终一致性,而不是依赖数据库的原生事务管理。下面是TCC事务的三个关键步骤:

  • Try:尝试执行阶段,完成所有业务可执行性的检查(保障一致性),并且预留好全部需用到的业务资源(保障隔离性)。

  • Confirm:确认执行阶段,不进行任何业务检查,直接使用 Try 阶段准备的资源来完成业务处理。Confirm 阶段可能会重复执行,因此本阶段所执行的操作需要具备幂等性。

  • Cancel:取消执行阶段,释放 Try 阶段预留的业务资源。Cancel 阶段可能会重复执行,也需要满足幂等性。

TCC事务的优势在于不依赖数据库的两阶段提交协议(2PC),因此更灵活,能够跨越不同的数据库和系统,适合于微服务架构中的分布式事务处理。然而,它要求业务逻辑层面的深度改造,每个服务都需要实现Try、Confirm、Cancel三个操作,并且对开发者的要求较高,增加了实现的复杂度。此外,TCC事务模式在高并发场景下可能会遇到资源锁定时间较长的问题,需要谨慎设计超时和重试机制。TCC 事务具有较强的隔离性, 缺点是业务侵入性很强

SAGA事务

SAGA(Saga Transaction)是一种分布式事务处理模式,特别适用于微服务架构中,用以解决跨服务的事务一致性问题。它通过一系列的本地事务来模拟一个全局事务,每个本地事务都具有幂等性,从而保证了整个事务过程的最终一致性。以下是SAGA事务的关键特点和组成部分:

  1. 基本概念
  • 事务链:SAGA将一个复杂的分布式事务分解为一系列的子事务(或称为Saga步骤),这些子事务按照一定的顺序执行,形成一个事务链。

  • 补偿操作:对于每个正向操作(即尝试完成业务逻辑的操作),都有一个对应的补偿操作(或称为撤销操作)。当某个子事务失败时,通过执行前面已完成子事务的补偿操作来回滚到事务开始前的状态,确保数据的一致性。

  • 最终一致性:SAGA不保证强一致性,而是追求最终一致性。这意味着在出现错误时,系统可能需要一段时间来恢复到一致状态。

  1. 关键特性
  • 幂等性:每个子事务及其补偿操作都需要实现幂等性,即多次执行同一操作,系统状态保持不变。

  • 异步与同步执行:SAGA中的子事务可以异步执行以提高性能,但补偿操作通常需要确保顺序执行,以正确维护事务的逻辑。

  • 故障恢复:通过记录事务状态和执行历史,SAGA能够自动或手动触发补偿操作来恢复系统状态。
    无锁机制:与传统的两阶段提交(2PC)不同,SAGA避免了在整个事务过程中持有资源锁,减少了锁竞争和死锁的风险。

  1. 实现挑战
  • 复杂性管理:随着业务逻辑复杂度的增加,设计和管理SAGA事务链及补偿逻辑变得越来越复杂。

  • 错误处理:需要有效机制来检测子事务的失败,并准确地执行相应的补偿操作,这要求有健壮的错误监控和恢复策略。

  • 性能与资源消耗:虽然SAGA提高了系统的响应速度,但补偿操作和状态跟踪可能会增加额外的资源开销。

综上,SAGA事务模式是处理分布式系统中事务一致性的一种灵活且强大的方法,尤其适合那些对性能和可用性有高要求的场景,但在设计和实施时需要仔细考虑其复杂性和潜在的挑战。

  • 27
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值