目录

一、本地事务

1、本地事务的基本特征

2、本地事务的隔离级别

①READ UNCOMMITTED(读未提交)

②READ COMMITTED(读提交)

③REPEATABLE READ(可重复读)

④SERIALIZABLE(序列化)

3、事务的传播行为

4、SpringBoot事务关键点

二、分布式事务

1、为什么要有分布式事务

2、CAP定理和BASE理论

①、CAP定理

②、面临的问题

③、BASE理论

④、强一致性、弱一致性、最终一致性

3、分布式事务的几种方案

①、2PC(二阶段提交)模式

②、柔性事务-TCC事务补偿方案

③、柔性事务-最大努力

④、柔性事务-可高消息+最终一致性方案(异步确保型)

4、Seata

①Seata的概述

②Seata的执行顺序

③Seata的使用


一、本地事务

1、本地事务的基本特征

ACID(原子性、一致性、隔离性、持久性)

原子性:一系列的操作整体不可拆分,要么同时成功,要么同时失败

 一致性:数据在事务的前后,业务整体一致。

         转账。A:1000;B:1000; 转 200 事务成功; A:800 B:1200

 隔离性:事务之间互相隔离。 

持久性:一旦事务成功,数据一定会落盘在数据库。

2、本地事务的隔离级别

①READ UNCOMMITTED(读未提交)

该隔离级别的事务会读到其它未提交事务的数据,此现象也称之为脏读。 

②READ COMMITTED(读提交)

一个事务可以读取另一个已提交的事务,多次读取会造成不一样的结果,此现象称为不可重复读问题,Oracle 和 SQL Server 的默认隔离级别。

③REPEATABLE READ(可重复读)

该隔离级别是 MySQL 默认的隔离级别,在同一个事务里,select 的结果是事务开始时时间点的状态,因此,同样的 select 操作读到的结果会是一致的,但是,会有幻读现象。MySQL 的 InnoDB 引擎可以通过 next-key locks 机制(参考下文”行锁的算法”一节)来避免幻读。

④SERIALIZABLE(序列化)

在该隔离级别下事务都是串行顺序执行的,MySQL 数据库的 InnoDB 引擎会给读操作隐式加一把读共享锁,从而避免了脏读、不可重读复读和幻读问题。

3、事务的传播行为

1、PROPAGATION_REQUIRED:如果当前没有事务,就创建一个新事务,如果当前存在事务,就加入该事务,该设置是最常用的设置。

2、PROPAGATION_SUPPORTS:支持当前事务,如果当前存在事务,就加入该事务,如果当前不存在事务,就以非事务执行。

3、PROPAGATION_MANDATORY:支持当前事务,如果当前存在事务,就加入该事务,如果当前不存在事务,就抛出异常。

4、PROPAGATION_REQUIRES_NEW:创建新事务,无论当前存不存在事务,都创建新事务。5、PROPAGATION_NOT_SUPPORTED:以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。

6、PROPAGATION_NEVER:以非事务方式执行,如果当前存在事务,则抛出异常。

7、PROPAGATION_NESTED:如果当前存在事务,则在嵌套事务内执行。如果当前没有事务,则执行与 PROPAGATION_REQUIRED 类似的操作。

4、SpringBoot事务关键点

 在同一个类里面,编写两个方法,内部调用的时候,会导致事务设置失效。原因是没有用到 代理对象的缘故。

解决:

0)、导入 spring-boot-starter-aop

1)、@EnableTransactionManagement(proxyTargetClass = true)

2)、@EnableAspectJAutoProxy(exposeProxy=true)

3)、AopContext.currentProxy() 调用方法

二、分布式事务

1、为什么要有分布式事务

2、CAP定理和BASE理论

①、CAP定理

1、C一致性

这⾥的⼀致性从不同⾓度有着各⾃的描述⽅式,在分布式系统中表现是每个节点的数据是相同;⽽对于客户端,表现是读操作所得到的结果永远是最新写⼊的。

2、A可用性

要让系统满⾜可⽤性,就是要保证⽆论除了所有节点出现故障的情况外,系统都能返回有效的响应,允许响应给客户端是旧的数据,但不能出现响应失败,超时的情况。

3、P分区容错

由于分布式系统多个节点往往部署在多个⽹络环境下进⾏相互通信,就难免出现⼀些⽹络故障,如⽹络丢包,⽹络消息延迟,⽹络中断等情况,会导致节点间的通信出现问题,数据同步操作⽆法完成,分区容错性就要求了系统即使在⽹络分区出现的情况下,能仍继续对客户端提供服务。

如何应用CAP定理?(三者选其二)

CAP定理指明了C,A,P三个属性⽆法同时满⾜,⽽在必有⽹络交互和数据同步的情况下,就⼀定会有延迟和数据丢失的情况,对于这种情况我们⼜必须接受且保证系统(不是单一系统)不能挂掉。所以分区容错性是必须要保证的,剩下的就是在⼀致性(C)和可⽤性(A)之间做选择了。选择了⼀致性,保证数据正确性,但也意味系统可能存在不可⽤的情况;⽽选择可⽤性,保证服务的⾼可⽤,但也意味数据可能出现不⼀致性的情况。接下来就探讨下应⽤采⽤CP架构,AP架构所各⾃的特点,以及如何根据不同的分布式场景选择适合的架构策略。

②、面临的问题

对于多数大型互联网应用的场景,主机众多、部署分散,而且现在的集群规模越来越大,所以节点故障、网络故障是常态,而且要保证服务可用性达到 99.99999%(N 个9),即保证P 和 A,舍弃 C。

③、BASE理论

它是对 CAP 理论的延伸,思想是即使无法做到强一致性(CAP 的一致性就是强一致性),但可以采用适当的采取弱一致性,即最终一致性。

BASE 是指

1、基本可用(Basically Available)

基本可用是指分布式系统在出现故障的时候,允许损失部分可用性(例如响应时间、功能上的可用性),允许损失部分可用性。需要注意的是,基本可用绝不等价于系统不可用。

①响应时间上的损失:正常情况下搜索引擎需要在 0.5 秒之内返回给用户相应的查询结果,但由于出现故障(比如系统部分机房发生断电或断网故障),查询结果的响应时间增加到了 1~2 秒。

②功能上的损失:购物网站在购物高峰(如双十一)时,为了保护系统的稳定性,部分消费者可能会被引导到一个降级页面。

2、软状态( Soft State)

软状态是指允许系统存在中间状态,而该中间状态不会影响系统整体可用性。分布式存储中一般一份数据会有多个副本,允许不同副本同步的延时就是软状态的体现。mysql replication 的异步复制也是一种体现。下图是对软状态的一个解释:

 3、最终一致性( Eventual Consistency)

最终一致性是指系统中的所有数据副本经过一定时间后,最终能够达到一致的状态。弱一致性和强一致性相反,最终一致性是弱一致性的一种特殊情况。

④、强一致性、弱一致性、最终一致性

从客户端角度,多进程并发访问时,更新过的数据在不同进程如何获取的不同策略,决定了不同的一致性。对于关系型数据库,要求更新过的数据能被后续的访问都能看到,这是强一致性。如果能容忍后续的部分或者全部访问不到,则是弱一致性。如果经过一段时间后要求能访问到更新后的数据,则是最终一致性。

3、分布式事务的几种方案

①、2PC(二阶段提交)模式

第一阶段:事务协调器要求每个涉及到事务的数据库预提交(precommit)此操作,并反映是否可以提交.

第二阶段:事务协调器要求每个数据库提交数据。 其中,如果有任何一个数据库否决此次提交,那么所有数据库都会被要求回滚它们在此事务中的那部分信息。

②、柔性事务-TCC事务补偿方案

前提:

刚性事务:遵循 ACID 原则,强一致性。

柔性事务:遵循 BASE 理论,最终一致性; 与刚性事务不同,柔性事务允许一定时间内,不同节点的数据不一致,但要求最终一致。

 TCC的核⼼思想是:针对每⼀个操作都需要注册⼀个和其相对应的确认和补偿的操作,他分为三个阶段Try、Confirm和Cance。

举例:A、B都有100元,他们在不同的银行,现在A要向B转30

 使⽤TTC事务,我们需要把之前实现的转账的代码拆分成三块,套到try-confirm-cancel中,由事务管理器%28协调管理%29推进AB两个try分别执⾏,在这个过程中,事务管理器会对AB进⾏监控,⼀旦任何⼀⽅出现了问题,就推进对⽅执⾏cancel;如果双⽅都没有异常,就推进AB执⾏confirm。如果在执⾏confirm或cancel过程中出现问题,就引⼊重试机制或由⼈⼯处理。由此可见TCC解决分布式事务的缺点⾮常的明显:1、代码侵⼊性很强,改造成本很⾼;2、实现难度也不⼩,回滚策略实现并不简单。

③、柔性事务-最大努力

④、柔性事务-可高消息+最终一致性方案(异步确保型)

4、Seata

①Seata的概述

Seata 是一款开源的分布式事务解决方案,致力于提供高性能和简单易用的分布式事务服务。Seata 将为用户提供了 AT、TCC、SAGA 和 XA 事务模式,为用户打造一站式的分布式解决方案。不适合高并发。

②Seata的执行顺序

专业术语:

TC (Transaction Coordinator) – 事务协调者

维护全局和分支事务的状态,驱动全局事务提交或回滚。

TM (Transaction Manager) – 事务管理器

定义全局事务的范围:开始全局事务、提交或回滚全局事务。

RM (Resource Manager) – 资源管理器

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

 首先,大事务TM告诉事务协调者TC,要开启一个全局事务了;分支事务在TC协调者注册,分支事务的状态TC都知道,任何一个分支事务失败,TC就会把所有的事务都回退。

③Seata的使用

1、创建一个undo_log表(为了回退数据使用)

-- 注意此处0.3.0+ 增加唯一索引 ux_undo_log
CREATE TABLE `undo_log` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT,
  `branch_id` bigint(20) NOT NULL,
  `xid` varchar(100) NOT NULL,
  `context` varchar(128) NOT NULL,
  `rollback_info` longblob NOT NULL,
  `log_status` int(11) NOT NULL,
  `log_created` datetime NOT NULL,
  `log_modified` datetime NOT NULL,
  `ext` varchar(100) DEFAULT NULL,
  PRIMARY KEY (`id`),
  UNIQUE KEY `ux_undo_log` (`xid`,`branch_id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;

2、下载服务器软件包,也就是TC协调者
3、导入依赖

        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-seata</artifactId>
            <version>2.1.1.RELEASE</version>
        </dependency>

4、修改服务器软件的配置文件(比如把file改为nacos),启动服务,去nacos观察是否含有这个服务
5、每个分布式事务配置自己的代理数据源,复制到每个服务,这里自动注入的时候不要写成私有的

@Configuration
public class MySeataConfig {

    @Autowired
    DataSourceProperties dataSourceProperties;

    @Bean
    public DataSource dataSource(DataSourceProperties dataSourceProperties) {

        HikariDataSource dataSource = dataSourceProperties.initializeDataSourceBuilder().type(HikariDataSource.class).build();
        if (StringUtils.hasText(dataSourceProperties.getName())) {
            dataSource.setPoolName(dataSourceProperties.getName());
        }

        return new DataSourceProxy(dataSource);
    }

}

6、把两个文件复制到每个分布式事务,并且修改file.conf里面的service

${spring.application.name}-fescar-service-group作为服务名注册到 Seata Server上

7、在分布式大事务加一个全局注解@GlobalTransactional
8、在每个小事务加一个注解@Transactional


版权声明:本文为qq_66068983原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
原文链接:https://blog.csdn.net/qq_66068983/article/details/127895349