分布式事务解决方案Seata原理剖析
(稍后上传我视频分享地址:)
默认是AT模式,我们就来剖析这AT模式到底是什么个原理
官网地址:http://seata.io/zh-cn/docs/overview/what-is-seata.html
整体机制是两阶段的提交
- 一阶段:业务数据和回滚日志记录在同一个本地事务中提交,释放本地锁和连接资源。
- 二阶段:
- 提交异步化,非常快速地完成。
- 回滚通过一阶段的回滚日志进行反向补偿。
这是官网介绍,如果你看不懂,那么我接下来说人话,这次必懂
首先明确它的一些概念:
写隔离
- 一阶段本地事务提交前,需要确保先拿到 全局锁 。
- 拿不到 全局锁 ,不能提交本地事务。
- 拿 全局锁 的尝试被限制在一定范围内,超出范围将放弃,并回滚本地事务,释放本地锁。
这里的概念是十分重要的,基本上已经讲清楚了它整个运作的原理
好,接下来我来说人话
背景
官网以两个节点操作同一个数据库为例进行说明,为了更加透彻的说清楚整个原理,我来以3个节点,分别操作3个数据库为例(订单,库存,账户)
当我们进行下单的时候,会经过如下步骤
- 创建订单
- 扣减库存
- 扣减余额
任何一个环节出了问题,那肯定完蛋了,我想你绝对不想出现钱扣完了,但是却提醒你还未支付吧,如果出现了,我想这个平台基本上没人敢来了
按照官网写隔离的定义,整个原理的过程如下(正常流程):
- 订单表插入一条记录
- 先获取当前记录的本地锁,使用本地事务进行提交前尝试获取全局锁,它是第一个执行的,因此一定能获取的到全局锁,然后提交本地事务,对于提交之前的数据进行undo_log的记录,对于提交之后的数据也进行undo_log的记录
- 库存表进行更新
- 同样的先获取本地事务,再获取全局锁,然后提交
- 账户表进行更新
- 同样的先获取本地事务,再获取全局锁,然后提交
如果出现异常,如何处理?
如果更新库存表的时候出现问题,则它开始回滚,并将回滚请求发送给TC,TC收到后,根据XID与Branch ID查找TC上各个分支上的事务,并根据记录的undo_log与操作后的数据进行比较,如果相同则说明没有被修改过,则反向补偿(也就是将操作之前的数据再执行还原回去)【因为本地事务提交后,本地锁就被释放了,这期间可能被其他事务操作】,如果不一样则需要人工处理或者采取其他措施
无论是否提交或者回滚,整个执行完之后都会异步的删除undo_log记录