场景
分布式事务用于在分布式系统中保证不同节点之间的数据一致性。
分布式事务是相对于单机事务/本地事务而言的,在分布式场景下,一个系统由多个子系统构成,每个子系统有独立的数据源。在微服务系统架构中,我们把每个子系统看成是一个微服务,每个微服务都可以维护自己的数据存储,各自保持独立,最后通过他们之间的互相调用组合出更复杂的业务逻辑。
举一个简单例子,在电商系统里,会有库存服务、订单服务,还有业务层的购物服务。生成订单的时候,需要调用库存服务扣减库存和调用订单服务插入订单记录。我们需要同时保证库存服务和订单服务的事务性。这就是分布式事务要解决的问题。
2PC
2pc, p-prepare, c-commit。 核心在于询问事务参与者是否事务操作成功


优点: 实现简单,MySQL,Oracle都有实现,针对强一致性,但可能存在数据不一致情况。
缺点:
- 同步阻塞: 事务参与者会在正式提交事务之前一直占用先关资源,比如A 2PC B,其他也要操作A或B就要阻塞
- 数据不一致: 由于网络问题或者事务协调者/管理者单机都会造成数据不一致情况。就是2PC中途死了,或者网络问题,会导致部分参与者没法收到COMMITE/ROLLBACK消息,导致不一致。
- 单点问题: 事务协调/管理者如果Prepare完了以后挂掉,参与者就一直卡在commit阶段。
3PC
比起2PC 多了一个询问阶段,并且引入了超时机制来解决单点问题

询问阶段-CanCommit:这一步不会执行事务操作,只会询问事务参与者能不能执行本地数据库操作
准备阶段: 所有事务参与者都返回可执行后,事务参与者才会执行本地数据库事务与操作,比如写redo log/undo log 日志
TCC
目前比较流行的,Try,Confirm,Cancel
- Try: 尝试执行,完成业务减产,并预留好业务资源
- Confirm: 确认执行,当所有事务参与者的Try执行都成功后执行Confirm,Confirm会处理Try预留的业务资源,否则会执行Cancel
- Cancel: 释放Try资源

一般实现TCC的组件:
- Hmily--- 多用于金融
MQ事务
RocketMQ, Kafka, Pulsar, QMQ都提供了事务相关操作,允许将生产,消费,处理定义为一个院子操作
下图为RocketMQ举例

- MQ发送方在消息队列开启一个事务,然后发送一个“Half消息”给MQ Server/Broker. 事务提交之前,Half消息对于MQ订阅方/消费者而言不可见
- “Half消息”发送成功的话,MQ发送方就开始执行本地事务
- MQ发送方的本地事务执行成功的话,“Half消息”就会变成正常消息,可以正常被消费,否则,会直接回滚
Saga
Saga属于长事务解决方案,其核心实现是将长事务拆分为多个本地短事务(本地短事务序列, 如下图

长事务-> T1, T2, T3 ... Tn , 共N哥本地短事务
每个段事务都有一个补偿动作 -> C1, C2 ... Cn

详情查阅:https://docs.microsoft.com/zh-cn/azure/architecture/reference-architectures/saga/saga
如果T1, T2, ~ Tn这些短事务都能顺利完成,整个事务就顺利结束,否则,将采用恢复模式。
反向恢复:
如果Ti事务失败,这补偿所有已完成的事务(一直执行Ci对Ti的补偿)、
执行顺序,T1, T2, T3.. Ti,Ci,Ci-1, ... C2, C1
正向恢复:
如果Ti事务失败,则一直重试,直到Ti成功
优点和缺点:
与TCC类似,这种对代码有侵入。但是他没有Try的动作,因此性能很高。理论上来说,补偿操作一定能执行成功,但是如果是宕机这种,那就没办法了,得通过日志,手动恢复。另外也因为他没有Try操作,Saga不能保证隔离性。
实现Saga的组件:
- ServiceComb Pack: 微服务应用的数据最终一致性解决方案
- Seata: TCC同款,你值得拥有
发表回复