在大多数场景下,应用只需要操作单一的数据库,这种情况下的事务称之为本地事务,本地事务的ACID特性,数据库直接提供支持。
在微服务架构下,如果应用操作的资源位于多个资源服务器,需要操作多个数据库时,该应用需要保证对于多个资源服务器的数据的操作,要么全部成功,要么全部失败。
这就涉及到了分布式事务,分布式事务就是为了解决不同资源服务器的数据一致性。
一、两阶段提交协议(2PC)
两阶段提交又称2PC(Two-Phase Commit Protocol)
,2PC是一个非常经典的强一致、中心化的原子提交协议。
这里的中心化是指协议中有两类节点:
- 一个是中心化协调者节点(Coordinator)
- 一个是N个参与者节点(Partcipant)
事务的提交过程分成了两个阶段来进行处理。 每个参与者将操作成败通知给协调者,再由协调者根据所有参与者的反馈情况,决定各参与者最终是否要提交操作还是终止操作。2PC执行成功,参与者全部同意;2PC执行失败,参与者任意一个不同意都会失败。
1、两阶段提交(Two-Phase Commit)
两阶段提交(Two-Phase Commit),是指将事务的提交(commit)过程划分为了 2个阶段(Phase)。
1.1 Prepare:提交事务请求
事务管理器给每个参与者发送 Prepare消息,每个数据库参与者在本地执行事务,并写本地的Undo/Redo日志,此时事务没有提交。 (Undo日志是记录修改前的数据,用于数据库回滚,Redo日志是记录修改后的数据,用于提交事务后写入数据文件)。
基本流程如下:
- 协调者事务询问,并开始等待
- 参与者执行事务
- 参与者反馈事务询问的响应
1.2 Commit:执行事务提交
如果协调者收到了各个参与者的执行失败或者超时消息时,直接给每个参与者发送回滚消息;否则,发送提交消息; 参与者根据协调者的指令执行提交或者回滚操作,并释放事务处理过程中使用的锁资源。
注意:必须在最后阶段释放锁资源。
1)正常提交事务
基本流程如下:
- commit 请求:协调者向所有参与者发送 Commit 请求。
- 事务提交 :参与者收到 Commit 请求后,执行事务提交,提交完成后释放事务执行期占用的所有资源。
- 反馈结果:参与者执行事务提交后向协调者发送 Ack 响应。
- 完成事务:协调者接收到所有参与者的 Ack 响应后,完成事务提交
2)中断事务
在执行 Prepare 步骤过程中,如果某些参与者执行事务失败、宕机或与协调者之间的网络中断,那么协调者就无法收到所有参与者的反馈响应,此时,协调者就会进入回退流程,对事务进行回退。
基本流程如下:
- rollback 请求:协调者向所有参与者发送 Rollback 请求。
- 事务回滚:参与者收到 Rollback 后,使用 Prepare 阶段的 Undo 日志执行事务回滚,完成后释放事务执行期占用的所有资源。
- 反馈结果:参与者执行事务回滚后向协调者发送 Ack 响应。
- 中断事务:协调者接收到所有参与者的 Ack 响应后,完成事务中断。
2、2PC存在的问题
1)同步阻塞问题
在 2PC 中的参与者是阻塞的。在第一阶段收到请求后就会预先锁定资源,一直到 commit 后才会释放。
参与者在等待协调者的指令时,其实是在等待其他参与者的响应,在此过程中,参与者是无法进行其他操作的,也就是阻塞了其运行。 倘若参与者与协调者之间网络异常导致参与者一直收不到协调者信息,那么会导致参与者一直阻塞下去。
2)单点故障
在 2PC 中,一切请求都来自协调者,所以协调者的地位是至关重要的,如果协调者宕机,那么就会使参与者一直阻塞并一直占用事务资源。尤其在第二阶段,协调者发生故障,那么所有的参与者还都处于锁定事务资源的状态中,而无法继续完成事务操作。
3)数据不一致
Commit 事务过程中 Commit 请求/Rollback 请求可能因为协调者宕机或协调者与参与者网络问题丢失,那么就导致了部分参与者没有收到 Commit/Rollback 请求,而其他参与者则正常收到执行了 Commit/Rollback 操作,没有收到请求的参与者则继续阻塞。这时,参与者之间的数据就不再一致了。
二、Seata简介
官方文档:https://seata.io/zh-cn/docs/overview/what-is-seata.html
1、Seata是什么
Seata 是一款开源的分布式事务解决方案,致力于提供高性能和简单易用的分布式事务服务。
Seata 将为用户提供了 AT、TCC、SAGA 和 XA 事务模式,为用户打造一站式的分布式解决方案。
2、Seata的三大角色
在 Seata 的架构中,一共有三个角色:
- TC (Transaction Coordinator) - 事务协调者:维护全局和分支事务的状态,驱动全局事务提交或回滚。
- TM (Transaction Manager) - 事务管理器:定义全局事务的范围:开始全局事务、提交或回滚全局事务。
- RM (Resource Manager) - 资源管理器:管理分支事务处理的资源,与TC交谈以注册分支事务和报告分支事务的状态,并驱动分支事务提交或回滚。
其中,TC 为单独部署的 Server 服务端,TM 和 RM 为嵌入到应用中的 Client 客户端。
3、Seata AT模式
Seata AT模式的核心是对业务无侵入,是一种改进后的两阶段提交,其设计思路如下:
- 一阶段:业务数据和回滚日志记录在同一个本地事务中提交,释放本地锁和连接资源。
- 二阶段:
- 提交异步化,非常快速地完成。
- 回滚通过一阶段的回滚日志进行反向补偿。
3.1 写隔离
- 一阶段本地事务提交前,需要确保先拿到 全局锁 。
- 拿不到 全局锁 ,不能提交本地事务。
- 拿 全局锁 的尝试被限制在一定范围内,超出范围将放弃,并回滚本地事务,释放本地锁。
3.2 读隔离
在数据库本地事务隔离级别 读已提交(Read Committed) 或以上的基础上,Seata(AT 模式)的默认全局隔离级别是 读未提交(Read Uncommitted) 。
如果应用在特定场景下,必需要求全局的 读已提交 ,目前 Seata 的方式是通过 SELECT FOR UPDATE 语句的代理。
来自官方文档,了解更多请查看官方文档。
– 求知若饥,虚心若愚。