分布式事务(二)———2PC/3PC(强一致性)解决方案

该系列参考:
https://www.jianshu.com/p/962271bbf4ea
https://blog.csdn.net/a745233700/article/details/122402303
https://cloud.tencent.com/developer/article/2048776
https://icyfenix.cn/

一、2PC两阶段提交

两阶段提交就是将事务提交拆成了准备阶段和提交阶段这两个阶段。 是一种强一致性设计,引入一个事务协调者的角色来协调管理各参与者(也可称之为各本地资源)的提交和回滚

数据库充当RM角色,应用需要充当TM的角色,把多个本地事务协调为全局统一的分布式事务。

在这里插入图片描述

1.一阶段提交

(1)假设第一阶段所有RM都返回Ok(准备成功),那么TM则向所有RM发送提交事务命令,然后等待所有事务都提交成功之后,返回事务提交成功

(2)假设第一阶段有一个RM返回失败了,那么TM就会向所有参与者发送回滚事务的请求,即分布式事务失败

(3)此阶段TM有超时机制,因为可能存在因为网络原因没有收到RM的响应或者RM挂了的情况,超时就会判断事务失败,全部回滚

2.二阶段提交

(1)假设二阶段执行回滚事务操作失败,则会不断重试回滚直到所有RM都回滚成功

(2)假设二阶段执行提交事务操作失败,也会不断重试,因为此时可能已经有RM已经提交成功了

3.存在的问题

  • 性能问题:所有事务参与者在等待其它参与者响应的时候都处于同步阻塞状态,无法进行其它操作
  • 单点问题:协调者(TM)在 2PC 中起到非常大的作用,发生故障将会造成很大影响。特别是在阶段二发生故障,所有参与者(RM)会一直等待状态,无法完成其它操作。
  • 数据一致性问题:协调者如果因为网络问题或者宕机了,向一部分参与者发送了commit,另一部分还没来得及发就宕机了,就会造成数据不一致。
  • 局限性:只适用于数据库层面的分布式事务

二、3PC

3PC 的出现是为了解决 2PC 的一些问题,相比于 2PC 它在参与者中也引入了超时机制,并且新增了一个阶段使得参与者可以利用这一个阶段统一各自的状态。
3PC 包含了三个阶段,分别是准备阶段、预提交阶段和提交阶段,对应的英文就是:
CanCommit、PreCommit 和 DoCommit

  • 阶段一(CanCommit):协调者(TM)向 参与者(RM)发出CanCommit?,询问是否可以提交事务了,如果所有参与者都反馈Yes则进入下一个阶段(此时不锁资源)
  • 阶段二(PreCommit):协调者(TM)向 参与者(RM)发出PreCommit命令,则参与者开始执行事务预提交(锁资源),执行完了返回Yes则进入下一个阶段,如果有一个no或者任何一方超时都会中断事务 ,释放资源
  • 阶段三(doCommit):协调者(TM)向 参与者(RM)发起doCommit命令,如果参与者都返回Yes 则每个参与者都会执行Commit命令,并反馈结果,全成功则事务结束,如果有一个no或者超时,则协调者发起回滚

相比2PC优缺点

优点:引进了超时机制,变相的优化了参与者同步阻塞的范围,也避免了协调者单点问题,阶段3协调者出现问题参与者也会提交事务

缺点:依旧存在数据不一致问题,阶段三假设协调者发出回滚命令,而某个参与者因网络问题没有收到命令,受机制影响也会提交事务,此时数据就不一致了;同时因为多引进了一个阶段,性能方面也会有所下降

三、Seata实现

DEMO详情见 : https://github.com/seata/seata-samples
Seata文档详情见: https://seata.io/zh-cn/docs/overview/what-is-seata.html

1.Seata-XA模式

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注解

2.Seata-AT模式

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;

系列文章

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值