如何将Seata与分布式事务完美融合进SpringCloud进阶实践?

摘要:Seata与分布式事务 先回顾下数据库事务吧: 原子性:一个事务中的所有操作,要么全部完成,要么全部不完成,不会结束在中间某个环节。事务在执行过程中发生错误,会被回滚到事务开始前的状态,就像这个事务从来没有执行过一样。 一致性:事务开始之前
Seata与分布式事务 先回顾下数据库事务吧: 原子性:一个事务中的所有操作,要么全部完成,要么全部不完成,不会结束在中间某个环节。事务在执行过程中发生错误,会被回滚到事务开始前的状态,就像这个事务从来没有执行过一样。 一致性:事务开始之前和事务结束之后,数据的完整性没有被破坏。 隔离性:数据库允许多个并发事务同时对其数据进行读写操作,隔离性可以防止多个事务并发执行时由于交叉执行而导致数据的不一致。事务隔离分为不同级别,包括:读未提交、读已提交、可重复读和串行化。 持久性:事务处理结束后,对数据的修改就是永久的,即使系统故障也不会丢失。 在分布式环境下,可能会出现这样的问题,比如下单购物,先调用库存服务减掉库存数量-》订单服务开始下单-》账户服务进行扣款。如果订单服务出现问题,就会导致库存扣了,但是没有生成订单,用户也没付款!导致货物丢失! 因此必须实现分布式事务,SPring Cloud Alibaba提供了分布式事务组件Seata Seata时一款开源的分布式事务解决方案,Seata将为用户提供AT、TCC、SAGA、XA事务模式。 实际上就是多了一个中间人(TC)来协调所有服务的事务。 分布式事务的解决方案 XA分布式事务协议-2PC(两阶段提交实现) 这里的PC指的时Prepare和Commit,也就是说它分为两个阶段,一个时准备阶段,一个时提交阶段,整个过程的参与者一共有两个角色,一个是事务的执行者,一个是事务的协调者,实际上整个分布式事务的运作都需要依靠协调者来维持: 准备阶段:一个分布式事务是由协调者来开启的 首先,协调者会向所有的事务执行者发送事务内容,等待所有的事务执行者答复 各个事务执行者开始执行事务操作,但不提交,并将undo和redo信息记录到事务日志中 如果事务执行者执行事务成功,那么告诉协调者yes,否则告诉协调者失败No,不能提交事务。 提交阶段:所有执行者都反馈完成后进入第二阶段 协调者检查各个执行者反馈的内容,如果都反馈成功,那么告诉所有执行者可以提交事务了,最后再释放锁资源 如果至少有一个执行者返回失败或者超时,那么就让所有执行者回滚,分布式事务执行失败。 这种方式看起来比较简单,但是存在以下几个问题: 事务协调者是核心角色,一旦出现问题,整个分布式事务都不能正常运行。 如果提交阶段发生网络问题,导致某些事务执行者没有收到协调者发来的提交命令。将导致这些执行者有些提交有些没提交,这样会发生错误! XA分布式事务协议-3PC(三阶段提交实现) 三阶段提交是在二阶段提交基础上的改进版本,主要加入了超时机制,同时在协调者和执行者中都引入了超时机制! 三个阶段分别为: CanCommit阶段: 协调者向执行者发送CanCommit请求,询问是否可以执行事务提交操作,然后等待执行者响应 执行者接收到请求后,如果其自身认为可以顺利执行事务,则返回yes,并进入预备状态,否则返回No PreCommit阶段: 协调者根据执行者的反应情况来决定是否可以进入第二阶段PreCommit ​ 如果所有执行者都返回yes,则协调者向所有执行者发送PreCommit请求,并进入PreCommit阶段,执行者收到请求后,会执行事务操作。并将undo和redo信息记录到事务日志中,如果执行成功,则返回成功响应 ​ 如果至少有一个执行者返回No,则协调者向所有执行者发送abort请求,所有执行者在收到请求或超过一段时间没收到任何请求时,会直接中断事务。 DoCommit阶段: 该阶段进行真正的事务提交。 协调者收到所有执行者发送的成功响应,那么就进入DoCommit状态,并向所有执行者发送DoCommit请求, 执行者收到DoCommit请求后,开始提交事务,并在完成事务提交后释放所有事务资源,并向协调者发送确认响应,协调者接收到所有执行者的确认之后,完成事务。(如果因为网络问题没收到DoCommit请求,执行者会在超时之后直接提交事务,虽然执行者只是猜测协调者返回的是DoCommit请求,但是因为前面的阶段都正常执行,所有能够在一定程度上认为本次事务是成功的,因此会直接提交) 协调者只要接收到一个失败的响应(或者响应超时),就会执行中断事务,协调者向所有执行者发送abort请求,执行者收到abort请求后,利用其在PreCommit阶段记录的undo信息来执行事务回滚,在回滚完成后释放所有的事务资源,并向协调者发送确认信息,协调者接收到反馈后执行事务中断。
阅读全文