该系列参考:
https://www.jianshu.com/p/962271bbf4ea
https://blog.csdn.net/a745233700/article/details/122402303
https://cloud.tencent.com/developer/article/2048776
https://icyfenix.cn/
两阶段提交就是将事务提交拆成了准备阶段和提交阶段这两个阶段。 是一种强一致性设计,引入一个事务协调者的角色来协调管理各参与者(也可称之为各本地资源)的提交和回滚
数据库充当RM角色,应用需要充当TM的角色,把多个本地事务协调为全局统一的分布式事务。
(1)假设第一阶段所有RM都返回Ok(准备成功),那么TM则向所有RM发送提交事务命令,然后等待所有事务都提交成功之后,返回事务提交成功
(2)假设第一阶段有一个RM返回失败了,那么TM就会向所有参与者发送回滚事务的请求,即分布式事务失败
(3)此阶段TM有超时机制,因为可能存在因为网络原因没有收到RM的响应或者RM挂了的情况,超时就会判断事务失败,全部回滚
(1)假设二阶段执行回滚事务操作失败,则会不断重试回滚直到所有RM都回滚成功
(2)假设二阶段执行提交事务操作失败,也会不断重试,因为此时可能已经有RM已经提交成功了
3PC 的出现是为了解决 2PC 的一些问题,相比于 2PC 它在参与者中也引入了超时机制,并且新增了一个阶段使得参与者可以利用这一个阶段统一各自的状态。
3PC 包含了三个阶段,分别是准备阶段、预提交阶段和提交阶段,对应的英文就是:CanCommit、PreCommit 和 DoCommit
优点:引进了超时机制,变相的优化了参与者同步阻塞的范围,也避免了协调者单点问题,阶段3协调者出现问题参与者也会提交事务
缺点:依旧存在数据不一致问题,阶段三假设协调者发出回滚命令,而某个参与者因网络问题没有收到命令,受机制影响也会提交事务,此时数据就不一致了;同时因为多引进了一个阶段,性能方面也会有所下降
DEMO详情见 : https://github.com/seata/seata-samples
Seata文档详情见: https://seata.io/zh-cn/docs/overview/what-is-seata.html
XA 规范 是 X/Open 组织定义的分布式事务处理(DTP,Distributed Transaction Processing)标准,XA 规范 描述了全局的TM与局部的RM之间的接口,几乎所有主流的数据库都对 XA 规范 提供了支持。
一阶段:
RM一阶段的工作:
(1)注册分支事务到TC;
(2)执行分支业务sql但不提交;
(3)报告执行状态到TC。
二阶段:
TC二阶段的工作:
(1) TC检测各分支事务执行状态;
如果都成功,通知所有RM提交事务;
如果有失败,通知所有RM回滚事务。
RM二阶段的工作:
(1)接收TC指令,提交或回滚事务。
实现步骤:
(1)修改application.yml配置文件
seata:
data-source-proxy-mode: XA # 开启数据源代理的XA模式
(2)给发起全局事务的入口方法添加@GlobalTransactional注解
AT模式同样是分阶段提交的事务模型,不过缺弥补了XA模型中资源锁定周期过长的缺陷。
一阶段:
RM一阶段的工作:
(1)注册分支事务到TC;
(2)记录undo-log(数据快照);
(3)执行业务sql并提交;
(4)报告事务状态。
二阶段:
RM二阶段的工作:
(1)提交时:删除undo-log即可;
(2)回滚时:根据undo-log恢复数据到更新前。
实现步骤:
(1)修改application.yml配置文件
seata:
data-source-proxy-mode: AT # 开启数据源代理的AT模式
(2)给发起全局事务的入口方法添加@GlobalTransactional注解
(3)每个服务的数据库都需要undo_log表
CREATE TABLE `undo_log` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`branch_id` bigint(20) NOT NULL,
`xid` varchar(100) NOT NULL,
`context` varchar(128) NOT NULL,
`rollback_info` longblob NOT NULL,
`log_status` int(11) NOT NULL,
`log_created` datetime NOT NULL,
`log_modified` datetime NOT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `ux_undo_log` (`xid`,`branch_id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;