文章目录
- 二阶段消息
- 本地消息表
- 本地消息表方案缺点:
- RocketMQ事务消息
- Rocketmq消息事务缺点
- 多种分布式事务协议支持
- SAGA:
- TCC: Try-Confirm-Cancel
- XA事务模式
- AT(Auto Transaction)模式
- 分布式事务框架
- SEATA
- 协调多节点数据同步
- 回滚
- 重试
二阶段消息
本地消息表
基于本地消息表的方案中,将本事务外操作,记录在消息表中
其他事务,提供操作接口
定时任务轮询本地消息表,将未执行的消息发送给操作接口。
操作接口处理成功,返回成功标识,处理失败,返回失败标识。
定时任务接到标识,更新消息的状态
定时任务按照一定的周期反复执行
对于屡次失败的消息,可以设置最大失败次数
超过最大失败次数的消息,不进行接口调用
等待人工处理
例如使用支付宝的支付场景,系统生成订单,支付宝系统支付成功后,调用我们系统提供的回调接口,回调接口更新订单状态为已支付。回调通知执行失败,支付宝会过一段时间再次调用。
本地消息表方案缺点:
消息数据和业务数据耦合,消息表需要根据具体的业务场景制定,不能公用。就算可以公用消息表,对于分库的业务来说每个库都是需要消息表的。
只适用于最终一致的业务场景。
RocketMQ事务消息
消息队列RocketMQ版提供类似XA或Open XA的分布式事务功能,通过消息队列RocketMQ版事务消息,能达到分布式事务的最终一致。
Rocketmq消息事务缺点
极端情况下,自动处理事务消息中的回查,解决了 RocketMQ 回查在极端情况下回出现的数据不一致问题(已申请了专利)
多种分布式事务协议支持
SAGA:
SAGA最初出现在1987年Hector Garcaa-Molrna & Kenneth Salem发表的论文SAGAS里。其核心思想是将长事务拆分为多个短事务,由Saga事务协调器协调,如果每个短事务都成功提交完成,那么全局事务就正常完成,如果某个步骤失败,则根据相反顺序一次调用补偿操作。
SAGA事务模式是DTM中最常用的模式,主要是因为SAGA模式简单易用,工作量少,并且能够解决绝大部分业务的需求。
例如我们要进行一个类似于银行跨行转账的业务,将A中的30元转给B,根据Saga事务的原理,我们将整个全局事务,切分为以下服务:
- 转出(TransOut)服务,这里转出将会进行操作A-30
- 转出补偿(TransOutCompensate)服务,回滚上面的转出操作,即A+30
- 转入(TransIn)服务,转入将会进行B+30
- 转入补偿(TransInCompensate)服务,回滚上面的转入操作,即B-30
整个SAGA事务的逻辑是:
- 执行转出成功=>执行转入成功=>全局事务完成
- 如果在中间发生错误,例如转入B发生错误,则会调用已执行分支的补偿操作,即:
执行转出成功=>执行转入失败=>执行转入补偿成功=>执行转出补偿成功=>全局事务回滚完成
在这个图中,我们的全局事务发起人,将整个全局事务的编排信息,包括每个步骤的正向操作和反向补偿操作定义好之后,提交给服务器,服务器就会按步骤执行前面SAGA的逻辑。
如果有正向操作失败,例如账户余额不足或者账户被冻结,那么dtm会调用各分支的补偿操作,进行回滚,最后事务成功回滚。
TCC: Try-Confirm-Cancel
TCC事务模式
什么是TCC,TCC是Try、Confirm、Cancel三个词语的缩写,最早是由 Pat Helland 于 2007 年发表的一篇名为《Life beyond Distributed Transactions:an Apostate’s Opinion》的论文提出。
TCC分为3个阶段
- Try 阶段:尝试执行,完成所有业务检查(一致性), 预留必须业务资源(准隔离性)
- Confirm 阶段:如果所有分支的Try都成功了,则走到Confirm阶段。Confirm真正执行业务,不作任何业务检查,只使用 Try 阶段预留的业务资源
- Cancel 阶段:如果所有分支的Try有一个失败了,则走到Cancel阶段。Cancel释放 Try 阶段预留的业务资源。
在设计上,TCC主要用于处理一致性要求较高、需要较多灵活性的短事务:
TCC如何做到更好的一致性
对于我们的 A 跨行转账给 B 的场景,如果采用SAGA,在正向操作中调余额,在补偿操作中,反向调整余额,那么会出现这种情况:如果A扣款成功,金额转入B失败,最后回滚,把A的余额调整为初始值。整个过程中如果A发现自己的余额被扣减了,但是收款方B迟迟没有收到资金,那么会对A造成非常大的困扰。
上述需求在SAGA中无法解决,但是可以通过TCC来解决,设计技巧如下:
- 在账户中的 balance 字段之外,再引入一个 trading_balance 字段
- Try 阶段检查账户是否被冻结,检查账户余额是否充足,没问题后,调整 trading_balance (即业务上的冻结资金)
- Confirm 阶段,调整 balance ,调整 trading_balance (即业务上的解冻资金)
- Cancel 阶段,调整 trading_balance (即业务上的解冻资金)
这种情况下,终端用户 A 就不会看到自己的余额扣减了,但是 B 又迟迟收不到资金的情况
XA事务模式
有了分布式事务的场景,就会有解决该问题的方式规范,XA规范就是解决分布式事务的规范。分布式事务的实现方式有很多种,最具有代表性的是由Oracle Tuxedo系统提出的 XA分布式事务协议。XA协议包括两阶段提交(2PC)和三阶段提交(3PC)两种实现。
XA是什么
XA是由X/Open组织提出的分布式事务的规范,XA规范主要定义了(全局)事务管理器™和(局部)资源管理器(RM)之间的接口。本地的数据库如mysql在XA中扮演的是RM角色
AT 模式是一种无侵入的分布式事务解决方案。
XA一共分为两阶段:
- 第一阶段(prepare):即所有的参与者RM准备执行事务并锁住需要的资源。参与者ready时,向TM报告已准备就绪。
- 第二阶段 (commit/rollback):当事务管理者™确认所有参与者(RM)都ready后,向所有参与者发送commit命令。
目前主流的数据库基本都支持XA事务,包括mysql、oracle、sqlserver、postgre
本地数据库是如何支持XA的:
XA start '4fPqCNTYeSG' -- 开启一个 xa 事务
UPDATE `user_account` SET `balance`=balance + 30,`update_time`='2021-06-09 11:50:42.438' WHERE user_id = '1'
XA end '4fPqCNTYeSG'
XA prepare '4fPqCNTYeSG' -- 此调用之前,连接断开,那么事务会自动回滚
-- 当所有的参与者完成了prepare,就进入第二阶段 提交
xa commit '4fPqCNTYeSG'
XA事务的特点是:
简单易理解
开发较容易,回滚之类的操作,由底层数据库自动完成
对资源进行了长时间的锁定,并发度低,不适合高并发的业务
AT(Auto Transaction)模式
分布式事务框架
SEATA
Seata 是一款开源的分布式事务解决方案,致力于提供高性能和简单易用的分布式事务服务。Seata 将为用户提供了 AT、TCC、SAGA 和 XA 事务模式,为用户打造一站式的分布式解决方案。
协调多节点数据同步
回滚
用户下单,订单服务更新,但库存库件失败。
库存可能无了,重试无意义。则回滚
重试
物流发货场景:物流服务发货,但订单服务状态更新失败,则不断重试
用户支付场景:订单状态待支付-> 用户支付后,如果接口超时,支付三方会不断重试回调接口