vlambda博客
学习文章列表

前世今生: 分布式事务1

要搞清分布式事务,我们先想一个问题,分布式事务产生的原因是什么?

如图所示:

CP是在保证数据强一致性前提下,尽量实现高可用(如过半写入)。

AP是在保证高可用的前提下,尽量实现数据一致性(如异步一致)。

前世今生: 分布式事务1

在ACID里,I是最难实现的。Isolation包含四个层级,如下表所示。在XA中,一般可以做到RC就可以了。

事务隔离级别 事务隔离描述 解决的问题 不能解决的问题
最低1 Read Uncommitted 脏读
2 Read Committed 脏读 不可重复读
3 Repeated  Read 脏读、不可重复读 幻读
最高4 Serialization 脏读、不可重复读、幻读

对于MySQL而言,它是通过RC+MVCC实现RR的效果。但ACID整体上是不靠谱的,为啥?

因为ACID只是满足数据隔离性,但没有做法并发控制。



如果面向于实际使用场景,我们把上图分布式实现区分一下,结果如下:

前世今生: 分布式事务1

也就是说,真实分布式场景中,80%是柔性事物,20%是刚性事务,即使在金融行业,也是这样。刚性事务通过2PC实现;柔性事物同步模式通过Sagas实现,异步模式通过事务消息实现。



我们先看一下刚性事务的最终实现:2PC。如下图所示。在下图中,RM管理共享资源,如DB。TM负责管理全局事务,如分配事务唯一标识、监控事务的执行进度、并负责事务的提交、回滚、失败、恢复等。


前世今生: 分布式事务1
2PC的缺点在于:它是同步阻塞模型、数据库锁定时间过长、全局锁(隔离级别串行化)并发低、不适合长事务场景(RM特别多的情况)。


3PC没有安全解决2PC的问题,但又引入了新的问题。由于实际场景几乎没人使用,因此我不做介绍。


在介绍了刚性事务2PC后,接下来我们介绍柔性事务。柔性事物的理念是BASE。

BASE理论指的是:

  • Basically Available(基本可用)

  • Soft state(柔性状态--->中间状态:业务中间态、数据中间态)

  • Eventually consistent(最终一致性)


我们举一个数据中间态的例子。一个转账业务,我们给转账业务数据分成两部分:可用金额要和冻结金额

前世今生: 分布式事务1

接下来,我们看柔性事物的实现,先看Saga。

Saga本质是将一个分布式事务分为多个本地事务。每个本地事务只有执行和补偿。我们拿银行业余来说,有转账业务,转账业务的补偿事务就是:转账冲正,如下图所示。如果转账失败,就调用转账冲正进行事务补偿。

前世今生: 分布式事务1

Saga的恢复模式分为:向后恢复(逆向补偿)和向前恢复(重试失败的事务)。



在隔离性方面,Sagas隔离是通过业务中间态实现的。例如金融系统的中间账户。

例如郭德纲向大魏转账,真实模式是:

郭德纲向中间账户转账失败,那么中间账户会删除记录。如果一段时间没删除,例如5s,那么中间账户就会想大魏转账。


前面提到的转账和冲正是互为逆方法。同样,CRUD中,insert和delete也是互为逆方法。因此我们需要为update操作提供逆方法。


那么,如何为update提供优雅的事务补偿呢?使用Seata AT。Seata AT就是在Sagas的基础上实现了自动补偿。目前自动补偿的方案都是往这个方向努力,看谁支持的 sql 语法更多,支持的db类型更多。

Seata AT实现的方法如下图:


未完待续...