分布式事务

发布时间 2023-09-27 17:24:17作者: Igang

传统事务

在讲分布式事务之前,先介绍一下传统的事务。事务具有ACID的特性,使用事务可以保证我们业务的原子性、一致性、隔离性和持久性。使用@Transaction注解来添加一个事务,@Transaction注解可以加载方法上,也可以加在类上。如果时加在类上,那么这个类所有的方法都将拥有事务。

原子性:事务中的所有操作必须全部成功或者全部失败,这个就是事务中必须要保证的原子性。影响事务的操作,一般是增删改。

一致性:事务开始前到事务结束后,数据状态需要一致。不能说我给你转了一千,钱转出去了你的余额却没有变。

隔离性:多个事务之间的操作需要相互隔离,互不影响。也就是说不能因为我现在在跟朋友视频电话,就导致发消息的功能不可用。

  • 隔离性具有四个隔离级别,

    • 读未提交级别下,会产生脏读、幻读、不可重复读的问题

    • 读已提交级别下,会产生幻读、不可重复读的问题,Oracle默认就是这个级别

    • 可重复读,会产生幻读的问题,mysql默认是这个级别

    • 串行化,不会有任何问题,但是相当于锁表,效率极低。这是最严格的事务,要求所有事务被串行执行,不能并发执行。因此不用这个级别。

     

不同的隔离级别会产生不同的问题

  • 脏读:一个事务读到了另一个事务没有提交的数据就是脏读,打个比方:事务A正在对数据库进行操作,执行了一系列的更新操作,在更新操作期间,更新的内容被事务B读取到了,但是事务A回滚了,这样事务B读到了数据库中不存在的数据,就出现了脏读。

  • 不可重复读:同一个事务中,连续读取两次,得到结果不一样。两个查询之间,被另外一个事务修改了数据的内容,产生内容的不一致。

  • 幻读:A事务去查询数据库条数,结果是n条,然后事务B对数据库进行了INSERT操作,导致A去更新数据的时候发现受影响条数是n+1,那么刚是不是读错了,就像产生了幻觉一样。

持久性:事务一旦提交,则永久的保存到磁盘,不可逆。

 

分布式事务

分布式事务是跨服务的。有多服务多数据库、多服务单数据库两种。通常一个库数据量比较大或者预期未来的数据量比较大,都会进行水平拆分,也就是分库分表。

CAP定理

数据库事务ACID 的四大特性,无法满足分布式事务的实际需求,这个时候又有一些新的大牛提出了一些新的理论。那就是CAP定理

它具有3个属性:

  • 一致性(Consistency) : 用户访问分布式系统中的任意节点,得到的数据必须是一致的。

    数据一致性分为强一致性、弱一致性、最终一致性

    • 如果时刻能保证看到的数据都是一致的,那么称之为强一致性。

    • 如果允许存在中间状态,只要求经过一段时间后,数据最终是一致的,则称之为最终一致性。

    • 此外,如果允许存在部分数据不一致,那么就称之为弱一致性。

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

  • 分区容错性(Partition tolerance) : 即使出现单个组件不可用,操作依然可以完成。

    • 分区(Partition):因为网络故障或其它原因导致分布式系统中的部分节点与其它节点失去连接,形成独立分区。

    • 容错(Tolerance):在集群出现分区时,整个系统也要持续对外提供服务。容忍出现分区的问题

但是这三个指标是无法同时满足的,因为网络是不可靠的。客户因素,没办法避免,所以P是一定要保证的。

  • CP:在一定时间内,等待集群节点进行数据同步后,对外提供访问

  • AP:在任何时间内,都对外访问,但是得到的数据可能不一样

  • CA:如果一定要满足CA,那就没有P,也就不是分布式环境了,是单节点。使用反证法证明不能同时出现,多个节点要想数据一致,需要时间同步。那么在这个时间内,一定不能对外访问,所以A不成立。如果可以对外访问,那么数据就不一致,所以C就不成立了。

 

BASE理论

Base的三个思想:

  • Basically Available(基本可用):分布式系统在出现故障时,允许损失部分可用性,即保证核心可用。譬如电商大促,为了应对大流量,暂时停止注册服务,这时注册服务就不可用,但是整个系统是可用的,所以叫基本可用

  • Soft State(软状态):在一定时间内,允许出现中间状态,比如临时的不一致状态。比如订单状态:待付款、已付款待发货、已发货、已签收、已结束

  • Eventually Consistent(最终一致性):虽然无法保证强一致性,但是在软状态结束后,最终达到数据一致。

 

分布式事务的解决思路

  1. AP模式:最终一致性

    各子事务分别执行和提交,允许出现结果不一致,然后采用弥补措施恢复数据即可,实现最终一致。

  • 譬如:增加了一条数据,后面有操作失败了,那么,补偿措施只需要把增加的那条数据删除即可

  • 因为子事务提交了,那么提交后的状态是一个中间状态,也就是软状态

 

  1. CP模式强一致性

    各个子事务执行后互相等待,同时提交,同时回滚,达成强一致。但事务等待过程中,处于弱可用状态。

  • 事务执行过程中,会锁定操作的资源,那么这个资源暂时是不可用的。所以整个系统是基本可用

 

  1. 子事务:分支事务

 

  1. 全局事务:事务协调者,用来监控和通知各个分支事务

 

 

Seata

seata 中三个主要架构分别是:

  • TC (Transaction Coordinator):事务协调者。负责维护全局和分支事务的状态,协调全局事务提交或回滚。监控和通知各个事务,包括分支事务和全局事务。

  • TM (Transaction Manager) :是事务管理器。定义全局事务的范围、开始全局事务、提交或回滚全局事务。执行事务。

  • RM (Resource Manager):资源管理器。管理分支事务处理的资源,与TC交谈以注册分支事务和报告分支事务的状态,并驱动分支事务提交或回滚。

 

XA模式

 

XA模型的优点是:事务是强一致性的,满足ACID的原则,实现比较简单,没有代码侵入

缺点是:必须要拿到所有数据源,而且数据源还要支持XA协议。目前MySQL中只有InnoDB存储引擎支持XA协议。因为一阶段需要锁定数据库资源,等待二阶段结束才释放,性能比较差,要把所有涉及到的数据都要锁定,是强一致性的,所以会产生长事务。

使用XA只需要导入依赖,加上配置信息以及加上@GlobalTransactional注解即可。

 

AT模式

 

TM会先告知TC开启全局事务,然后调用分支RM,RM将分支事务注册到TC。然后RM会执行sql并直接提交,这个时候就会记录更新前后的快照,并将快照保存到 undo log表中,接着会将事务状态报告给TC。到TM向TC发起提交或回滚全局事务时,TC会检查分支的事务状态,然后决定时提交还是回滚。如果是提交,就会删除undo log表中记录的这条快照,如果是回滚,就会去恢复undo log表中更新前的快照信息。

 

 

 

 

2PC

2PC就是标准的XA模型,它就是二阶段提交,是XA规范定义的 数据一致性协议。

二阶段提交协议将节点分为:

  • 协调者角色(事务管理器)

  • 参与者角色(资源管理器)

2PC角色中,事务管理器的角色,负责协调多个数据库(资源管理器)的事务,

协调者角色(事务管理器Coordinator),负责向参与者发送指令,收集参与者反馈,做出提交或者回滚决策 参与者角色(资源管理器Participant),接收协调者的指令执行事务操作,向协调者反馈操作结果,并继续执行协调者发送的最终指令

 

3PC

三阶段提交(3PC)协议对 2PC协议的一种扩展。

针对2PC的缺点,研究者提出了3PC,即Three-Phase Commit。

作为2PC的改进版,3PC将原有的两阶段过程,重新划分为CanCommit、PreCommit和do Commit三个阶段。

3PC 协议将 2PC 协议的准备阶段一分为二,从而形成了三个阶段:

所谓的三个阶段分别是:询问,然后再锁资源,最后真正提交