第八章:SpringCloud for Alibaba 集成Seata之分布式事务

声明

本系列全部文章由75888丶编写,非盗用他人文档,由于是根据教学视频进行整理,可能存在类似,保证全部手打,非复制粘贴他人文档、代码。从文章的编写到代码,全部跟进行了测试,保证可用。
文章末尾提供了githup、gitee的源代码地址,如有疑问或问题,可在文章底部留言,我们共同讨论。如解决您的问题,欢迎留言点赞!最后感谢您的阅读。
SpringCloud、SpringBoot群聊:958923746

分布式事务

什么是事务?

事务是访问数据并可能更新数据库中各种项的一个程序执行单元,一个事务是由一组SQL组成。拥有ACID特性:原子性、持久性、隔离性、一致性

什么是本地事务?

@Transcational,大多数情境下,我们只需要操作单一的数据库,这种情况就称为本地事务(Local Transcation),本地事务的ACID是数据库直接支持的。

常见分布式解决方案?

  1. seata阿里分布式方案(AT)
  2. 消息队列(TCC)
  3. saga(SAGA)
  4. XA(XA)

共性:他们都是二阶段提交(2PC)

什么是两阶段提交?

分别是:Prepare与Commit

Prepare(预处理阶段):提交事务请求

Commit:提交事务

通常要引进一个协调者对象,有协调者统一判断事务是进行提交还是回滚。再由参与者来提交或者回滚

二阶段期间做了什么?

  1. 首先由协调者向参与者发起请求,参与者进行做出业务上的判断,是否满足事务的提交。
  2. 参与者将数据(提交的数据redo,回滚的数据undo)进行保存。参与者有可能存储SQL,有可能存储的是数据。(都是为了保证数据的一致性与原子性,进行提交或者回滚)弊端:堵塞阶段,无法做其他事情。
  3. 如果都返回yes,则表示参与者都可以进行提交,协调者通知各个参与者进行提交请求。
  4. 参与者收到请求后将进行提交操作,数据入库,并清除redo与undo的资源。返回应答给协调者告知成功

如果在参与者提交成功后没有返回响应给协调者,怎么办?

发生概率很小,无法保证百分百成功。

二阶段问题?

1、同步堵塞

参与者在等待协调者的指令时,其实是在等待其他参与者的响应,在此过程中,参与者是无法进行其他操作的。也就是堵塞了运行。倘若参与者与协调者之间网络异常导致参与者一直收不到协调者信息,那么参与者一直堵塞。

2、单点在2PC中,一切请求来自协调者,所以协调者的地位是至关重要的,如果协调者宕机,那么会使参与者会一直堵塞并一直占用事务。

如果协调者也是分布式的,使用选主方式提供服务,那么在一个协调者挂掉后,可以选取另一个协调者继续后序的服务,可以解决单点问题。但是新的协调者无法知道上一个事务的全部状态信息(例如以等待Preare响应时长等)所以无法顺利处理上一个事务。

3、数据不一致CCommit事务过程中Commit请求/Rollback请求可能因为协调者宕机或协调者与参与者网络问题丢失,那么就导致部分参与者收到Commit/Rollback请求,而其他的参与者正常收到了请求操作。没有收到请求的参与者会继续堵塞。这时参与者时间的数据可能不一致了。

当参与者执行Commit/Rollback后会向协调者发送ACK,然后协调者不论是否收到所有参与者的ACK,该事务也不会有其他补救措施了,协调者能做的也就是等待超时后向事务发起者返回一个“我不确定该事务是否成功”。

4、环境依赖性

协调者Prepare请求发出后,等待响应,然而如果有参与者宕机或者协调者之间的网络中断,都会导致协调者无法收到所有参与者的响应,那么在2PC中,协调者会等待一定时间,超时后会触发事务中断,在这个过程中,协调者和所以参与者都是堵塞的,这种机制对现实的的环境来说太苛刻了。

为什么要用seata?

解决分布式事务场景所遇到的问题。

什么是seata?

Seata 是阿里开源的分布式事务框架,属于二阶段提交模式。是开源的分布式事务解决方案,致力于在微服务架构下提供高性能和简单的分布式事务服务。
AT模式是阿里首推的事务模式,阿里收费的seata是GTS

AT模式(Auto Transcation)

无侵入的分布式事务解决方案,事务控制在DB层完成

一阶段准备

在一阶段,seata会拦截业务SQL,首先解析SQL语义,找到业务SQL要更新的业务数据,在业务数据被更新前,将其保存成before image,然后执行业务SQL更新业务数据,在业务数据更新后,在将其保存成after image,最后生成行锁。以上操作都是一个数据库事务完成,保证了一阶段操作的原子性。

加行锁的原因:事务隔离,防止其他事务可以读到,防止脏读

redo:执行更新后的数据,加行锁。

undo:执行前,通过where条件查询元数据,将数据进行保存

二阶段提交

因为数据在一阶段已经更新到数据库,二阶段只需要将一阶段保存的快照数据进行删除,行锁进行删除即可

二阶段回滚

需要将一阶段的数据进行回滚,还原业务数据。首先对redo中的数据与数据库中的数据进行比较,防止脏写,如果数据一致就说明没有脏写,可以还原数据。还原数据需要逆向SQL,进行undo中的数据还原到数据库。出现脏写就需要人工干预。

TCC模式(Try、Confirm、Cancel)

  1. 需要自己在业务中实现Try、Confirm、Cancel三个操作。事务一阶段执行Try方式,二阶段执行Confirm,二阶段回滚执行Cancel方法。
  2. 侵入性比较强,并且自己实现事务控制逻辑
  3. 整个过程中没有锁,性能更强,控制更加灵活

常见TCC框架:BeyeTCC、TCC-transcation、Himly

MQ消息一致性方案

原理与TCC差不多,结合TCC理念可以通过MQ完成消息一致性。

流程:

  1. try中发送预备消息到rocketMQ
  2. confirm中进行更新数据,如果更新有问题,调用cancel删除RocketMQ中的消息。反之修改没问题,将数据发送给RocketMQ,给消费者进行处理
  3. 如果在confirm宕机,则MQ对数据进行会查,默认15次,如果没有查到则将消息删除

源码提供(照顾某些git很卡的同学,提供gitee地址)

githup地址:https://github.com/wangsh6379/SpringCloud-for-Alibaba
gitee地址:https://gitee.com/75888/spring-cloud-for-alibaba
上一篇:Spring cloud nacos注册中心 seata分布式事务


下一篇:docker - seata 使用nacos注册中心和配置中心,集成feign-rest调用,