本文的主要内容分为四个方面:事务概念、分布式事务问题、解决方案概览、开源方案Seata及AT模式。
一、事务概念回顾
事务定义:事务是并发控制的单位,业务定义的一个操作序列,这些操作要么都执行,要么都不执行,它是一个不可分割的工作单位。
本地事务:本地事务是指仅操作单一事务资源的、不需要全局事务管理器进行协调的事务,也称为数据库事务或传统事务。
执行模式:
![215636e3d67d0253b1e2449924dd68ae.png](https://i-blog.csdnimg.cn/blog_migrate/811c94811f553bd48db0fc9a55d36263.jpeg)
分布式事务:
随着SOA架构、微服务的流行,以及业务复杂后进行服务化拆分,数据库垂直拆分后会有多实例库的事务需求,会出现对应的分布式事务。
定义:分布式事务是指事务的参与者、支持事务的服务器、资源服务器以及事务管理器分别位于不同的分布式系统的不同节点之上
场景:
1、 跨数据库实例 2、 跨服务 3、 混合式分布式事务
![5fa853f1d05afa6f0262b42015015ff6.png](https://i-blog.csdnimg.cn/blog_migrate/179a7695876a03ec6ae8e8864a1ad083.jpeg)
二、分布式事务问题
场景:调用其他的服务,需要判断返回状态后在执行后续的逻辑、一个服务操作了多个数据源的场景
问题:单靠业务逻辑判断或者补偿会非常复杂,几乎无法保证事务的基本语义和基本特性
三、解决方案概览
1. 二阶段提交
2PC,Two-phase commit protocol,即两阶段提交协议。它引入了一个事务协调者角色,来管理各个参与者(就是各数据库资源)
![d7391e914fde60fdf413f97de11b7dd7.png](https://i-blog.csdnimg.cn/blog_migrate/0d9c61e3d179f13567f9eaa46e5a0338.jpeg)
![ec2d20e4bc58d35746524b93c3c3e8ff.png](https://i-blog.csdnimg.cn/blog_migrate/03ec451f17f3783a0513e65e358ea4d9.jpeg)
问题:a 同步阻塞 :二阶段提交过程中,所有参与事务操作的节点处于同步阻塞状态,无法进行其他的操作
b 单点问题:协调者发生故障,那么所有的参与者还都处于锁定事务资源的状态中,而无法继续完成事务操作
c 数据不一致:如果分布式节点出现网络分区,某些参与者未收到命令,出现数据不一致
2. 三阶段提交
3PC 把 2PC 的准备阶段再次一分为二,这样三阶段提交就有 CanCommit、PreCommit、DoCommit 三个阶段
改进:1 将prepare拆分成cancommit和precommit,减少资源浪费 2 引入超时机制。同时在协调者和参与者中都引入超时机制,等待超时后,继续commit
问题:仍然无法解决数据一致性问题
3. 其他方案
TCC 补偿型事务:TCC(Try、Confirm、Cancel)是两阶段提交的一个变种
基于消息的分布式事务
j2ee中的JTA参考XA两阶段规范,与XA兼容
华为的 ServiceComb:https://servicecomb.apache.org/cn/docs/introduction/
蚂蚁金服XTS,DTX
阿里巴巴TXC
开源方案 Seata:http://seata.io/zh-cn
四、 开源方案seata
Seata是一款开源的分布式事务解决方案,致力于提供高性能和简单易用的分布式事务服务。Seata 将为用户提供了 AT、TCC、SAGA 和 XA 事务模式,为用户打造一站式的分布式解决方案
AT 模式是一种无侵入的分布式事务解决方案。在 AT 模式下,用户只需关注自己的“业务 SQL”,用户的 “业务 SQL” 作为一阶段,Seata 框架会自动生成事务的二阶段提交和回滚操作。
关键实现代码
在一阶段,Seata 会拦截“业务 SQL”,解析 SQL 语义后找到“业务 SQL”要更新的数据,在数据被更新前,将其保存成“before image”,然后执行“业务 SQL”更新数据,在数据更新之后,再将其保存成“after image”,最后生成行锁。以上操作全部在一个数据库事务内完成,这样保证了一阶段操作的原子性。
二阶段如果是提交的话,因为“业务 SQL”在一阶段已经提交至数据库, 所以 Seata 框架只需将一阶段保存的快照数据和行锁删掉,完成数据清理即可
二阶段如果是回滚的话,Seata 就需要回滚一阶段已经执行的“业务 SQL”,还原业务数据。回滚方式便是用“before image”还原业务数据;但在还原前要首先要校验脏写,对比“数据库当前业务数据”和 “after image”,如果两份数据完全一致就说明没有脏写,可以还原业务数据,如果不一致就说明有脏写,出现脏写就需要转人工处理
关键设计问题,可以自己学习前思考,边学习边寻找答案,会事半功倍:
1. 全局锁和checklock
2. XID传递问题
3. 失败重试,补偿等措施
4. 异步的设计和处理 ,比如分支的提交使用异步队列
如果看到这里,说明你喜欢这篇文章,请 转发、点赞。微信搜索「web_resource」,关注后回复「进群」或者扫描下方二维码即可进入无广告交流群。
↓扫描二维码进群↓
推荐阅读
3. SpringSecurity + JWT 实现单点登录