分布式事务 + Seata详解

一. 事务相关问题

1. 事务的分类

1.1 本地事务

  • 本地事务是指事务只在单个数据库、文件系统或单个节点上进行,不涉及到跨多个资源或跨多个节点的事务,本地事务通常用来维护单个系统或应用程序的数据完整性和一致性。

1.2 分布式事务

  • 分布式事务是指涉及多个不同的节点、资源或系统的事务。分布式事务主要用于管理分布式系统中的数据一致性和原子性操作。在分布式事务中,多个节点或应用程序对一组相关的操作进行了协调,以确保这些操作或操作集是整体的、原子的。

2. 事务的基本特性 [ACID]

2.1 原子性(Atomicity)

  • 原子性是指事务是不可分割的工作单位,要么全部执行完成,要么全部回滚到之前的状态,不会中途中断或失败。

2.2 一致性(Consistency)

  • 一致性是指事务开始前和完成后,数据库的状态必须是一致的。在一致的状态中,所有数据和外键约束必须保持完整性。

2.3 隔离性(Isolation)

  • 隔离性是指事务并发操作时,多个并发事务之间要相互隔离,不能被其他事务的操作所影响。

2.4 持久性(Durability)

  • 持久性是指一旦事务被提交,它的结果就是永久性的,无论发生什么情况,例如系统失败、系统崩溃或关机,都不应该对已提交的事务结果产生影响。

3. 事务并发存在的问题

3.1 脏读(Dirty Read)

  • 脏数据是指未进行提交的数据。脏读是指一个事务在处理过程中读取了另一个未提交事务的数据。

3.2 不可重复读(Non-repeatable Read)

  • 不可重复读是指在单个事务中,先后读取同一条记录,而事务在两次读取之间该数据被其它事务所修改,导致事务中多次查询同一个数据时得到的结果不同。

3.3 幻读(Phantom Read)

  • 幻读是指在单个事务中,同一查询操作在不同时间内返回的结果集不一致,通常是由于多个并发事务对数据集进行修改而造成的。当一个事务读取数据时,其他的事务又进行了更新或插入新数据,就会造成幻读。

4. 事务的隔离级别

4.1 读未提交(Read uncommitted)

  • 所有事务都可以看到其他未提交事务的执行结果。本隔离级别是最低的隔离级别,虽然拥有超高的并发处理能力及很低的系统开销,但很少用于实际应用。因为采用这种隔离级别只能防止更新丢失问题,不能解决脏读,不可重复读及幻读问题。

4.2 读已提交(Read committed)

  • 一个事务只能看见已经提交事务所做的改变。这种隔离级别可以防止脏读问题,但会出现不可重复读幻读问题。这也是大多数数据库系统的默认隔离级别,但不是MySQL默认的,MySQL默认为可重复读

4.3 可重复读(Repeatable read)

  • 指的是在一个事务内多次查询相同的数据时,返回的结果应该是一致的。它确保同一事务的多个实例在并发读取数据时,会看到同样的数据行。这种隔离级别可以防止脏读不可重复读,但无法处理幻读问题。

4.4 串行化(Serializable)

  • 这是最高的隔离级别,它通过强制事务排序,使之不可能相互冲突,从而解决上面提到的所有并发问题,但可能导致大量的超时现象和锁竞争,通常数据库不会用这个隔离级别,我们需要其他的机制来解决这些问题:乐观锁和悲观锁。

二. 分布式事务理论

1. CAP理论

  • 一个分布式系统最多只能同时满足一致性、可用性和分区容错性这三项中的两项,而分区容忍性(P)是必须实现的,所以产生了APCP模式。

  • 问题:为什么分区容错性一定要满足?可用性和一致性的互斥又是如何产生的?

    当我们的数据项只在一个节点保存时,一旦出现分区,其他部分就无法访问到数据,所以我们需要把数据分布在多个节点上,那么当出现分区后,这个数据项就可能到各个分区里,从而提高容错性。但是当我们把数据放在多个节点中后,又会带来数据一致性的问题,为了保证数据一致,在同步过程中,被同步的节点会被锁定读写操作,直到同步完成才会放开,所以锁住的过程中,这个节点就不具有可用性了,而如果不锁住,又无法完成一致性同步。

(1)一致性(Consistency)

  • 一致性是指用户访问分布式系统中的任意节点时,得到的数据必须一致,包括读取和写入操作。

(2)可用性(Availability)

  • 可用性是指用户访问集群中的任意健康节点时,必须能得到响应,而不是超时或拒绝。

(3)分区容错性(Partition Tolerance)

  • 分区容错性是指系统在遇到某节点或者网络分区故障的时候,仍然能够对外满足可用性或一致性的服务。

2. BASE理论

(1)基本可用(Basically Available)

  • 系统保证在故障或异常情况下,依然能够提供基本的服务能力,允许损失部分可用性,保证核心可用。

(2)软状态(Soft State)

  • 不追求数据的强一致性,允许数据存在中间状态,在一段时间内数据可以存在不一致。

(3)最终一致性(Eventually Consistent)

  • 系统最终能够保证数据的一致性,但不必要求在每个时刻数据都是强一致的。

三. Seata

1. Seata架构

1.1 事务协调者 TC(Transaction Coordinator)

  • 维护全局和分支事务的状态,协调全局事务提交或回滚。

1.2 事务管理器 TM(Transaction Manager)

  • 控制全局事务的边界,负责开启一个全局事务,并最终发起全局提交或全局回滚的决议。

1.3 资源管理器 RM(Resource Manager)

  • 控制分支事务,处理分支事务的资源,与TC交谈以注册分支事务和报告分支事务的状态,并驱动分支事务提交或回滚。

2. Seata的事务模式

2.1 XA模式

分布式事务 + Seata详解_第1张图片

  • 阶段一:(RM工作)

    (1)RM注册分支事务到TC中

    (2)执行分支的业务SQL,但是不进行提交

    (3)向TC报告事务的执行状态

  • 阶段二:(TC工作)

    (1)TC检测各分支事务的执行状态

    (2)若全部成功:TC通知所有RM提交事务

    (3)若存在失败:TC通知所有RM回滚事务

  • 阶段二:(RM工作)

    (1)接收TC的通知指令,进行提交或回滚事务

2.2 AT模式

分布式事务 + Seata详解_第2张图片

  • 阶段一:

    (1)解析SQL,得到需要执行的SQL指令的相关信息(操作类型,表,条件语句等)

    (2)生成查询前镜像:根据解析得到的条件信息,生成查询语句,定位数据

    (3)执行分支的业务SQL

    (4)生成查询后镜像:根据前镜像的结果,通过主键定位数据

    (5)插入回滚日志:把2次镜像数据及业务 SQL 相关的信息组成一条回滚日志记录,插入到Undo_Log表中

    (6)提交前,向TC注册分支,被操作数据的全局锁,拿不到全局锁则不提交数据,若超出尝试范围,则直接回滚本地事务

    (7)本地事务提交:更新的业务数据和Undo_Log一并提交

    (8)向TC报告事务的执行状态

  • 阶段二:(回滚)

    (1)收到 TC 的分支回滚请求,开启一个本地事务

    (2)通过 XID 和 Branch ID 查找到相应的Undo_Log记录

    (3)数据校验:拿Undo_Log中的后镜与当前数据进行比较,如果有不同,说明数据被当前全局事务之外的动作做了修改

    (4)根据Undo_Log中的前镜像和业务SQL的相关信息执行回滚

    (5)提交本地事务,并把分支事务回滚的结果上报给 TC

  • 阶段二:(提交)

    (1)收到TC的分支提交请求,把请求放入一个异步任务的队列中,马上返回提交成功的结果给TC

    (2)异步任务阶段的分支提交请求将异步和批量地删除相应Undo_Log记录

2.3 TCC模式

分布式事务 + Seata详解_第3张图片

  • 阶段一:(Try)

    (1)分支事务进行资源的检查和预留,但并不会真正修改数据

    (2)向TC报告事务的执行状态

  • 阶段二:(Confirm)

    (1)分支事务执行实际的操作,将数据真正提交到数据库中

    (2)通知TC该分支已完成Commit操作

  • 阶段二:(Cancel)

    (1)如果有分支无法完成提交,将进行回滚,释放Try阶段预留的资源

  • TCC模式的问题

  • 空回滚:

    (1)定义:对于一个分布式事务,因为某些原因未执行Try阶段,直接调用了二阶段的Cancel方法。而调用Cancel时,需要识别这是否是一个空回滚,如果是则直接返回成功

    (2)解决:定义额外的事务控制表,用来记录Try阶段是否执行过,Cancel调用时去表中查询该记录,如果存在则正常回滚,不存在则进行空回滚

  • 业务悬挂:

    (1)定义:对于已经空回滚的业务,Seata框架认为Cancel执行成功后,整个分布式事务就已经结束,但这之后Try恢复执行,则永远不可能到达Confirm或Cancel阶段,资源就会一直处于预留状态,这就是悬挂

    (2)解决:Cancel阶段执行时插入记录,执行Try操作时,先判断是否已经回滚,如果是则阻止回滚后的Try操作

  • 幂等性问题:

    (1)定义:TC通知RM提交或回滚时,RM如果已经执行完操作但未给TC返回执行结果,TC就会重复通知直到收到结果

    (2)解决:记录每个分支事务的执行状态,执行前进行查询来判断状态,如果已经处理,则直接返回成功即可

2.4 SAGA模式

分布式事务 + Seata详解_第4张图片

  • 阶段一:

    (1)SAGA模式中,多个分支事务组成一个全局事务,每个分支事务直接提交

  • 阶段二:

    (1)如果全部成功,则直接结束

    (2)如果某一个分支事务执行失败,SAGA实行全局撤回,将之前提交的所有分支事务全部回滚

2.5 四种模式对比

分布式事务 + Seata详解_第5张图片

你可能感兴趣的:(知识总结梳理,分布式,java)