• 分布式事务


    1、事务

    事务 (TRANSACTION) 是作为单个逻辑工作单元执行的一系列 SQL 操作,这些操作作为一个整体一起向系统提交,要么都执行、要么都不执行。

    1.1 ACID事务的特点

    1. 原子性:即不可分割性,事务要么全部被执行,要么就全部不被执行。 

    2. 一致性或可串性:事务的执行使得数据库从一种正确状态转换成另一种 正确状态

    3. 隔离性:在事务正确提交之前,不允许把该事务对数据的任何改变提供 给任何其他事务

    4. 持久性:事务正确提交后,其结果将永久保存在数据库中,即使在事务 提交后有了其它故障,事务的处理结果也会得到保存。

    1.2 事务并发带来的问题

    脏读(Dirty read): 当一个事务正在访问数据并且对数据进行了修改, 而这种修改还没有提交到数据库中,这时另外一个事务也访问了这个数据, 然后使用了这个数据。因为这个数据是还没有提交的数据,那么另外一个事务读到的这个数据是“脏数据”,依据“脏数据”所做的操作可能是不正确的。

    丢失修改(Lost to modify): 指在一个事务读取一个数据时,另外一个 事务也访问了该数据,那么在第一个事务中修改了这个数据后,第二个事务 也修改了这个数据。这样第一个事务内的修改结果就被丢失,因此称为丢失 修改。 例如:事务1读取某表中的数据A=20,事务2也读取A=20,事务1修 改A=A-1,事务2也修改A=A-1,最终结果A=19,事务1的修改被丢失。

    不可重复读(Unrepeatableread): 指在一个事务内多次读同一数据。 在这个事务还没有结束时,另一个事务也访问该数据。那么,在第一个事务 中的两次读数据之间,由于第二个事务的修改导致第一个事务两次读取的数 据可能不太一样。这就发生了在一个事务内两次读到的数据是不一样的情 况,因此称为不可重复读。

    幻读(Phantom read): 幻读与不可重复读类似。它发生在一个事务 (T1)读取了几行数据,接着另一个并发事务(T2)插入了一些数据时。在 随后的查询中,第一个事务(T1)就会发现多了一些原本不存在的记录,就 好像发生了幻觉一样,所以称为幻读。

    不可重复读和幻读区别: 不可重复读的重点是修改,比如多次读取一 条记录发现其中某些列的值被修改,幻读的重点在于新增或者删除比如 多次读取一条记录发现记录 增多或减少了

    1.3 事务的隔离级别

    READ-UNCOMMITTED(读取未提交): 最低的隔离级别,允许读取尚未提交 的数据变更,可能会导致脏读、幻读或不可重复读。

    READ-COMMITTED(读取已提交): 允许读取并发事务已经提交的数据,可 以阻止脏读,但是幻读或不可重复读仍有可能发生。

    REPEATABLE-READ(可重复读): 对同一字段的多次读取结果都是一致 的,除非数据是被本身事务自己所修改,可以阻止脏读和不可重复读,但幻 读仍有可能发生。

    SERIALIZABLE(可串行化): 最高的隔离级别,完全服从ACID的隔离级 别。所有的事务依次逐个执行,这样事务之间就完全不可能产生干扰,也就 是说,该级别可以防止脏读、不可重复读以及幻读。

    2、分布式事务

    2.1 什么情况下会需要分布式事务?

    一、微服务之间通过远程调用完成事务操作

    二、单体系统访问多个数据库实例

    比如:用户信息和订单信息分别在两个Mysql实例存储,用户管理系统删除用户信息,需要分别删除信息以用户的订单信息。由于数据分布在不同的数据库实例,需要通过不同的数据库连接去操作数据

    三、多服务访问同一个数据库实例

    比如:订单微服务和存库微服务即使访问同一个数据库也会产生分布式事务,原因就是跨JVM进程,两个微服务持有了不同的数据库连接进行数据库操作。

    2.2 如何解决分布式问题

    使用消息中间件
    手写代码解决分布式事务
    使用第三方组件 --->Seata 阿里巴巴的产品

    3、seata简介

    seata的官网如下:

    https://seata.io/zh-cn/docs/ops/deploy-guide-beginner.html
    Seata 是一款开源的分布式事务解决方案,致力于提供高性能和简单易用的分布式事务服务。 Seata 将为用户提供了 AT TCC SAGA XA 事务模 式,为用户打造一站式的分布式解决方案。

    Seata分TC、TM和RM三个角色,TC(Server端)为单独服务端部署,TM和RM(Client端)由业务系统集成。

    TC (Transaction Coordinator) - 事务协调者

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

    TM (Transaction Manager) - 事务管理器

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

    RM (Resource Manager) - 资源管理器

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

    Seata的执行流程如下:

    1. A 服务【订单微服务】的 TM[ 事务发起者 ] TC[seata 服务端 ] 申请开启一个全局事务, TC 就会创建一个全局事务并返回一个唯一的 XID
    2. A 服务开始远程调用 B 服务【账户微服务】,此时 XID 会在微服务的调用链上传播
    3. B 服务的 RM TC 注册分支事务,并将其纳入 XID 对应的全局事务的管辖
    4. B 服务执行分支事务,向数据库做操作
    5. 全局事务调用链处理完毕, TM 根据有无异常向 TC 发起全局事务的提交或者回滚
    6. TC 协调其管辖之下的所有分支事务, 决定是否回滚

    4、搭建seata服务器

    4.1 下载seata1.3.0

    这里需要注意的是springcloud的版本要和seata的版本相对应,下面是版本对照表

    我们可以从这个网址下载所需要的seata的版本

    4.2 解压

    4.3 修改seata的保存地址

    seata的保存位置默认为本地,我们之后会搭建seata集群,为了让 seata 集群信息可以共享,我们应该修改它的保存位置

    4.3.1 修改conf/file.conf配置文件

    4.3.2 引入MySQL的jar包

    seata默认引入的jar包没有包含MySQL的jar包,需要我们从lib/jdbc目录下复制下相对应的MySQL的jar包到lib目录下

    4.3.3 创建数据库并导入表结构

    这里的数据库表结构可以在源码中找到

    4.4 指定seata的注册中心地址和配置中心的内容

    4.4.1 修改conf/registry.conf配置文件

    4.4.2 修改nacos配置中心的配置文件

    nacos中需要存储哪些配置文件呢?

    4.4.3 生成配置文件

    先开启seata服务

     

    使用 nacos/nacos-fonfifig.sh 把配置信息放入 nacos 配置中心

    执行完之后上面这个页面会自动关闭,这时我们去nacos配置中心会发现生成的这些配置文件

    如果想人为指定nacos配置中心的地址

    在 Windows Terminal 下打开 Git 安装目录 bin 文件夹,执行 .\sh.exe 进入 sh 命令窗口,在 sh 窗口下导航至 \seata-1.3.0\script\config-center\nacos 文件夹,执行以下命令将配置导入 Nacos;

    1. # 导入,t:命名空间,g:分组,p:端口号,h:IP地址
    2. sh nacos-config.sh -h 127.0.0.1 -p 8848 -g SEATA_GROUP -t 5e22d16b-da6c-4f3f-8f3a-41cb501f18e5

    4.5 配置微服务客户端

    4.5.1 在每个微服务的数据库中创建unlog表

    4.5.2 在每个微服务中添加seata依赖

    1. <dependency>
    2. <groupId>com.alibaba.cloudgroupId>
    3. <artifactId>spring-cloud-starter-alibaba-seataartifactId>
    4. dependency>

    4.5.3 修改每个微服务的配置文件

    然后添加seata注册中心和配置中心的相关配置

    1. # 指定seata服务器所在nacos的注册中心的地址
    2. seata:
    3. registry:
    4. type: nacos
    5. nacos:
    6. # 指定seata服务器所在的注册中心地址
    7. server-addr: localhost:8848
    8. username: nacos
    9. password: nacos
    10. # 指定seata服务器所在的注册中心地址 默认SEATA_GROUP
    11. group: SEATA_GROUP
    12. # 指定seata服务器在注册中心的服务名称 默认seata-server
    13. application: seata-server
    14. config:
    15. type: nacos
    16. nacos:
    17. server-addr: localhost:8848
    18. username: nacos
    19. password: nacos
    20. group: SEATA_GROUP

    4.5.4 添加全局事务注解

    @Transactional //只是本地事务 它只能回滚本地自己连接的数据库 无法回滚其他微服务连接数据库。
    @GlobalTransactional //全局事务

    然后启动项目进行测试,访问

    localhost:8001/order/addOrder?userId=1&productId=1&money=100&count=10

    先验证下单成功

    验证下单失败

  • 相关阅读:
    Python学习(五):字典核心底层原理
    Spring Boot 配置文件
    【渲染数学-01】如何模拟静态流(上)
    图片1920x1080分辨率怎么调 ?图片如何修改分辨率?
    【网页设计】HTML做一个属于我的音乐页面(纯html代码)
    【Linux】CPU当前频率及调整CPU频率操作
    Vue项目中,el-image实现按钮触发大图预览模式
    实时分布式低延迟OLAP数据库Apache Pinot探索实操
    SSM+服装管理系统 毕业设计-附源码080948
    玩转Vue3之shallowRef和shallowReactive
  • 原文地址:https://blog.csdn.net/Dumpling_skin/article/details/126539606