关于如何实现一个Saga分布式事务框架的思考

关于Saga模式的介绍,已经有一篇文章介绍的很清楚了,链接在这里:分布式事务:Saga模式

关于TCC模式的介绍,也已经有一篇文章介绍的很清楚了,链接在这里:关于如何实现一个TCC分布式事务框架的一点思考

1. 子事务动作

Saga的子事务包含两个动作:T和C;TCC的子事务包含三个动作:Try、Commit、Cancel。Saga和TCC相比没有“预留动作”。以经典的A转账给B的例子来说:

Saga:

  • T1(A账户余额减少)
  • C1(还原A账户余额)
  • T2(B账户余额增加)
  • C2(还原B账户余额)

TCC

  • Try1(A账户余额预扣)
  • Commit1(A账户余额减少)
  • Cancel1(还原A账户余额)
  • Try2(B账户余额预加)
  • Commit2(B账户余额增加)
  • Cancel2(还原B账户余额)

2. 子事务≠数据库事务

这个需要从两个层面进行展开:

  • 首先,无论是Saga还是TCC,一个子事务都包含多个数据库事务。上面的例子中:无论是Saga的T和C,还是TCC的Try、Commit和Cancel,都是一个个完整的数据库事务,天然的具有数据库自身的ACID特性。
  • 其次,无论是Saga还是TCC,一个子事务可能并不是数据库操作:比如调用文件服务器进行文件上传、比如发送一封邮件。

3. ACID

这个也需要从两个层面进行展开:

  • 首先,从数据库事务层面,在Saga和TCC的中间阶段是不满足一致性(业务逻辑的一致性,而非数据库约束)的
  • 其次,从整个分布式事务层面,在Saga和TCC的中间阶段是不满足隔离性的,其他事务可以看到当前事务执行的中间状态

不过以上两个问题都可以通过分布式锁来解决,例如:在执行事务之前对A和B的账户进行加锁,拒绝其他事务的读写操作,但是这样会降低效率。强一致性和高可用性二选一

4. 幂等

关于幂等,要区分子事务是否满足ACID。

  • 子事务满足ACID:例如子事务为数据库事务,那么无论是TCC还是Saga,每一个动作都都可以顺利完成或顺利回滚,则不需要幂等性
  • 子事务不满足ACID:例如子事务为上传文件, Saga和TCC的T可幂等可不幂等,如果T幂等则可以认为T必定成功则Saga的C和TCC的Cancel不再需要,如果Saga和TCC的T不幂等则Saga的C和TCC的Cancel必须能够处理T部分完成的情况。Saga的C和TCC的Cancel必须幂等,否则当回滚执行失败系统无法确定该再次尝试回滚还是就此放弃。TCC的Commit不存在是否幂等问题,因为按照TCC的规则一旦Try成功则Commit必定成功。

 

 

posted @ 2019-11-08 15:41  柚子苹果果  阅读(1707)  评论(0编辑  收藏  举报