Bootstrap

架构03-事务处理

零、文章目录

架构03-事务处理

1、本地事务实现原子性和持久性

(1)事务类型
  • **本地事务:**单个服务、单个数据源
  • **全局事务:**单个服务、多个数据源
  • **共享事务:**多个服务、单个数据源
  • **分布式事务:**多个服务、多个数据源
(2)事务意义
  • **一致性:**保证系统中的数据正确,不同数据间不会产生矛盾。
  • ACID特性:
    • **原子性(Atomicity):**多个对数据的修改要么同时成功,要么一起被撤销。
    • **隔离性(Isolation):**不同业务处理过程中的数据读写互相独立,不会彼此影响。
    • **持久性(Durability):**成功提交的数据修改能够正确地被持久化,不丢失数据。
(3)事务场景
  • **事务的概念:**最初源于数据库,但现代信息系统中,包括数据库、缓存、事务内存、消息、队列、对象文件存储等场景都可能涉及事务处理。
  • **复杂性:**单个服务使用单个数据源时较容易实现一致性,但涉及多个数据源或多个服务时变得困难。
(4)本地事务
  • **定义:**仅操作特定单一事务资源的事务,不需要全局事务管理器进行协调。
  • **适用场景:**单个服务使用单个数据源。
  • 实现原理
    • **原子性:**保证事务的多个操作要么都生效,要么都不生效。
    • **持久性:**保证事务生效后,修改的内容不会因任何原因被撤销或丢失。
(5)实现方法
  • Commit Logging:
    • **原理:**先将修改数据的操作记录到日志中,日志记录成功后,再对数据进行修改。
    • **优点:**简单清晰,易于实现。
    • **缺点:**性能较低,不允许在事务提交前写入变动数据。
  • Write-Ahead Logging:
    • **原理:**允许在事务提交前写入变动数据,通过 Undo Log 和 Redo Log 来实现崩溃恢复。
    • 步骤:
      • **分析阶段(Analysis):**扫描日志,找出待恢复的事务集合。
      • **重做阶段(Redo):**重演历史,将包含 Commit Record 的日志写入磁盘。
      • **回滚阶段(Undo):**根据 Undo Log 回滚未提交的事务。
    • **优点:**性能较高,允许提前写入数据。
    • **缺点:**实现复杂,涉及多种日志类型和复杂的恢复机制。
(6)ARIES理论
  • **定义:**基于语义的恢复与隔离算法,现代主流关系型数据库在事务实现上深受其影响。
  • **核心思想:**通过 Write-Ahead Logging 实现高效且严谨的日志记录与故障恢复。
  • 组合策略:
    • **FORCE:**事务提交后,要求变动数据必须同时完成写入。
    • **STEAL:**事务提交前,允许变动数据提前写入。
    • **最佳组合:**NO-FORCE + STEAL,性能最高但实现复杂。

2、数据库事务隔离性实现原理

(1)隔离性与并发
  • **定义:**隔离性保证每个事务各自读、写的数据互相独立,不会彼此影响。
  • **并发关系:**如果没有并发,所有事务全都是串行的,不需要任何隔离。但在现实中,并发是不可避免的,因此需要通过加锁等方式实现串行的数据访问。
(2)数据库提供的三种锁
  • 写锁(Write Lock / X-Lock)
    • 只有持有写锁的事务才能对数据进行写入操作。
    • 数据加持着写锁时,其他事务不能写入数据,也不能施加读锁。
  • 读锁(Read Lock / S-Lock)
    • 多个事务可以对同一个数据添加多个读锁。
    • 数据被加上读锁后不能被加上写锁,其他事务不能对该数据进行写入,但仍然可以读取。
    • 持有读锁的事务可以将读锁升级为写锁,然后写入数据。
  • 范围锁(Range Lock)
    • 对某个范围直接加排他锁,在这个范围内的数据不能被读取,也不能被写入。
    • 范围锁不仅禁止修改已有数据,还禁止在该范围内新增或删除任何数据。
(3)本地事务的四种隔离级别
  • 可串行化(Serializable)
    • **隔离强度:**最高
    • **实现方式:**对事务所有读、写的数据全都加上读锁、写锁和范围锁。
    • **性能影响:**并发能力最低,吞吐量最低。
  • 可重复读(Repeatable Read)
    • **隔离强度:**次高
    • **实现方式:**对事务所涉及的数据加读锁和写锁,持续到事务结束,但不加范围锁。
    • **问题:**幻读问题(Phantom Reads),即在事务执行过程中,两个完全相同的范围查询得到了不同的结果集。
  • 读已提交(Read Committed)
    • **隔离强度:**中等
    • **实现方式:**对事务涉及的数据加的写锁持续到事务结束,但读锁在查询操作完成后立即释放。
    • **问题:**不可重复读问题(Non-Repeatable Reads),即在事务执行过程中,对同一行数据的两次查询得到了不同的结果。
  • 读未提交(Read Uncommitted)
    • **隔离强度:**最低
    • **实现方式:**对事务涉及的数据只加写锁,持续到事务结束,完全不加读锁。
    • **问题:**脏读问题(Dirty Reads),即在事务执行过程中,一个事务读取到了另一个事务未提交的数据。
(4)多版本并发控制(MVCC)
  • 基础原理:
    • **版本管理:**对数据库的任何修改都不会直接覆盖之前的数据,而是产生一个新版副本与老版本共存。
    • **版本字段:**每一行记录都有两个看不见的字段:CREATE_VERSION 和 DELETE_VERSION,记录事务 ID。
    • 读取策略:
      • 可重复读:总是读取 CREATE_VERSION 小于或等于当前事务 ID 的记录,取最新版本。
      • 读已提交:总是取最新的版本即可,即最近被 Commit 的那个版本的数据。
  • **适用场景:**主要针对“读 + 写”场景的优化,如果是“写 + 写”场景,仍需加锁。
(5)乐观加锁与悲观加锁
  • **悲观加锁:**认为事务之间数据存在竞争是普遍情况,因此一开始就加锁。
  • **乐观加锁:**认为事务之间数据存在竞争是偶然情况,因此不一开始就加锁,而是出现竞争时再采取补救措施。
  • **性能影响:**竞争剧烈时,乐观锁可能更慢。

3、全局事务和共享事务

(1)全局事务
  • **定义:**全局事务(Global Transactions)适用于单个服务使用多个数据源的场景,是一种在分布式环境中追求强一致性的事务处理方案。
  • 实现方式:
    • XA 协议:
      • **定义:**1991年X/Open组织提出的事务处理框架,定义了全局事务管理器(Transaction Manager)和局部资源管理器(Resource Manager)之间的通信接口。
      • 核心组件:
        • 事务管理器:协调全局事务。
        • 资源管理器:驱动本地事务。
    • JTA(Java Transaction API):
      • javax.transaction.TransactionManager:用于容器事务管理。
      • javax.transaction.UserTransaction:用于手动开启、提交和回滚事务。
      • javax.transaction.xa.XAResource:资源定义接口,实现该接口的资源支持JTA。
  • 两段式提交(2PC):
    • 阶段:
      • **准备阶段:**协调者询问参与者是否准备好提交。
      • **提交阶段:**协调者根据参与者回复决定提交或回滚。
    • **优点:**保证了事务的一致性。
    • 缺点:
      • **单点问题:**协调者宕机会影响所有参与者。
      • **性能问题:**多次远程调用和数据持久化导致性能较差。
      • **一致性风险:**网络不稳定可能导致数据不一致。
  • 三段式提交(3PC):
    • 阶段:
      • CanCommit:协调者询问参与者事务是否可以完成。
      • PreCommit:参与者准备提交。
      • DoCommit:协调者发送提交指令。
    • **优点:**改善了单点问题和回滚时的性能问题。
    • **缺点:**并未解决一致性风险问题,甚至可能增加一致性风险。
(2)共享事务
  • **定义:**共享事务(Share Transactions)是指多个服务共用同一个数据源。
  • 实现方式:
    • **数据源与数据库的区别:**数据源是提供数据的逻辑设备,不一定与物理设备一一对应。
    • **场景:**多个微服务共用同一个数据库。
    • 方案:
      • **共享数据库连接:**同一应用进程内的不同持久化工具共享数据库连接。
      • **交易服务器:**新增中间角色,各服务通过交易服务器与数据库交互。
      • **消息队列:**使用消息队列服务器代替交易服务器,通过消息驱动更新数据库。
  • 局限性:
    • **性能问题:**数据库是系统中的瓶颈,难以扩展。
    • **伪需求:**实际应用中较少使用,更多是理论上的可行性。

4、分布式事务

(1)分布式事务的挑战
  • 分布式事务的复杂性
    • **DTP 模型:**分布式事务相对于数据源而言,不涉及服务
    • **分布式服务环境下的事务处理机制:**涉及多个服务同时访问多个数据源
  • **事例场景:**Fenix’s Bookstore
    • **服务拓扑:**账号、商家、仓库服务集群
    • CAP 问题:
      • **一致性问题:**数据未及时同步导致错误交易
      • **可用性问题:**数据同步过程中暂停服务
      • **分区容忍性问题:**网络分区导致服务不正确
  • CAP 取舍
    • **CP 系统:**放弃可用性,保证一致性和分区容忍性
      • **RDBMS 集群:**通过共享磁盘避免网络分区
      • **HBase:**RegionServer 宕机导致数据离线
    • **AP 系统:**放弃一致性,保证可用性和分区容忍性
      • **NoSQL 库:**节点独立提供服务,可能出现不一致数据
      • **Redis 集群:**节点独立提供服务,可能出现不同数据
(2)CAP 理论与 ACID 原则的矛盾
  • CAP 理论
    • **一致性(C):**所有节点数据一致
    • **可用性(A):**系统不间断提供服务
    • **分区容忍性(P):**部分节点失联时系统仍能正确提供服务
  • ACID 原则
    • **原子性(A):**事务中的所有操作要么全部成功,要么全部失败
    • **一致性(C):**事务执行前后,数据库保持一致状态
    • **隔离性(I):**并发事务互不干扰
    • **持久性(D):**事务一旦提交,结果永久保存
  • 矛盾点
    • **CAP 理论:**分布式系统中最多只能同时满足两个特性
    • **ACID 原则:**要求事务具有强一致性
(3)可靠事件队列
  • 弱一致性
    • **定义:**牺牲一致性,追求可用性和分区容忍性
    • **最终一致性:**数据在一段时间内未被修改,最终达到一致状态
  • 实现方式:可靠事件队列
    • **BASE 模型:**基本可用、软状态、最终一致性
    • 操作时序:
      • 用户发送交易请求
      • 系统评估操作顺序
      • 账户服务扣款并写入消息表
      • 消息服务轮询消息表,发送消息
      • 服务节点处理消息并返回结果
      • 消息服务重试直至成功
    • 关键点
      • **幂等性:**消息重复发送不会导致重复操作
      • **最大努力交付:**通过持续重试保证可靠性
(4)TCC (Try-Confirm-Cancel)
  • 特点:
    • **强隔离性:**通过Try阶段预留资源,确保事务的隔离性。
    • **业务侵入性:**需要将业务逻辑拆分为Try、Confirm和Cancel三个阶段,对业务代码有较高侵入性。
    • **高性能:**在业务执行时只操作预留资源,减少锁和资源争用,具有较高的性能潜力。
  • 实现过程:

- **Try阶段:**
    * 检查业务可行性。
    * 预留业务资源。
- **Confirm阶段:**
    * 使用Try阶段准备的资源完成业务处理。
    * 满足幂等性,可能重复执行。
- **Cancel阶段:**
    * 释放Try阶段预留的业务资源。
    * 满足幂等性,可能重复执行。
  • 适用场景:
    • **强隔离性要求:**如在线书店的库存管理,需要避免超售问题。
    • **高性能要求:**在业务逻辑允许的情况下,可以通过TCC提高系统吞吐量。
(5)SAGA
  • 特点:
    • **灵活性:**将大事务拆分为多个小事务,每个小事务都有对应的补偿操作。
    • **低业务侵入性:**不需要为资源设计冻结状态和撤销冻结的操作,补偿操作相对容易实现。
    • **最终一致性:**通过正向恢复或反向恢复策略,确保最终一致性。
  • 实现过程:
    • 子事务拆分:
      • 将大事务T拆分为多个子事务T1, T2, …, Tn。
    • 补偿操作设计:
      • 为每个子事务Ti设计对应的补偿操作Ci。
      • 满足幂等性和交换律。
    • 恢复策略:
      • **正向恢复:**如果Ti提交失败,重试直至成功。
      • **反向恢复:**如果Ti提交失败,执行Ci补偿操作直至成功。
  • 适用场景:
    • **灵活性要求高:**如银行转账场景,无法要求银行冻结款项。
    • **最终一致性要求:**在业务逻辑允许的情况下,可以通过SAGA确保最终一致性。
(6)AT事务(异步提交模式)
  • 特点:
    • **异步提交:**每个数据源单独提交,立即释放锁和资源,提高系统吞吐量。
    • **牺牲隔离性:**可能产生脏写和脏读,需要通过全局锁机制来避免。
    • **自动补偿:**通过保存SQL快照,自动生成逆向SQL进行补偿。
  • 实现过程:
    • SQL拦截:
      • 自动拦截所有SQL,保存修改前后结果的快照,生成行锁。
    • 本地事务提交:
      • 通过本地事务提交快照和行锁。
    • 分布式事务提交/回滚:
      • 成功提交时,清理日志数据。
      • 需要回滚时,根据日志数据生成逆向SQL进行补偿。
  • 适用场景:
    • **高吞吐量要求:**在业务逻辑允许的情况下,通过异步提交提高系统吞吐量。
    • **最终一致性要求:**在可以接受一定程度的脏写和脏读的情况下,确保最终一致性。
;