资料来源:www.bilibili.com/video/BV1FJ…
分布式事务
一、基本理论
-
事务
- 本地事务
- 分布式事务
-
分布式事务场景
- 场景1:微服务架构。比如下单的同时请求订单微服务减库存。订单和库存在不同的数据库实例上。
- 场景2:微服务架构。在上面情况即使订单和库存在同一个数据库实例上也会有分布式事务
- 场景3:单体应用。用户和订单在两个数据库实例上。
-
分布式事务的理论CAP
- 一致性,分为强弱
- 可用性
- 分区容忍性(系统基本能力):1)主数据库通过网络向从数据同步数据,可以认为主从数据库部署在不同的分区,通过网络进行交互。 2)当主数据库和从数据库之间的网络出现问题不影响主数据库和从数据库对外提供服务。 3)其一个结点挂掉不影响另一个结点对外提供服务。
-
组合
- CP:放弃一致性,追求分区容忍性和可用性。这是很多分布式系统设计时的选择。
- AP:放弃可用性,追求一致性和分区容错性,我们的zookeeper其实就是追求的强一致,又比如跨行转账,一次转账请求要等待双方银行系统都完成整个事务才算完成。
- AP:单体应用,常用的关系型数据库
-
BASE理论
- 基本可用
- 软状态
- 最终一致性
二、2PC(两阶段提交)/3PC(三阶段提交)
1. 2PC;Prepare和Commit
2PC问题:
情况一:协调者挂了,参与者没挂。只要找一个协调者的替代者。没有数据一致性问题。 情况二:参与者挂了,协调者没挂。
- 第一个是挂了就挂了,没有再恢复。不会导致数据一致性问题。
- 第二个是挂了之后又恢复了,这时如果他有未执行完的事务操作,直接取消掉,然后询问协调者目前我应该怎么做,协调者就会比对自己的事务执行记录和该参与者的事务执行记录,告诉他应该怎么做来保持数据的一致性。
情况三:参与者挂了,协调者也挂了
- 协调者和参与者在第一阶段挂了。新选出来的协调者可以询问各个参与者的情况,再决定是进行commit还是roolback。因为还没有commit,所以不会导致数据一致性问题。
- 第二阶段协调者和参与者挂了
- 挂了的参与者在挂之前并没有接收到协调者的指令。没有一致性问题。
- 挂了的参与者接收到指令之后还没来的及做commit或者rollback操作。没有一致性问题。
- 挂了的这个参与者在挂之前已经执行了操作,但是由于他挂了,没有人知道他执行了什么操作。如果是commit 没关系,但是如果是rollback 是有问题的,数据一致性。
2. 3PC:3PC最关键要解决的就是协调者和参与者同时挂掉的问题,所以3PC把2PC的准备阶段再次一分为二,这样三阶段提交就有CanCommit、PreCommit、DoCommit三个阶段。
与两阶段提交不同的是,三阶段提交有两个改动点。
1、引入超时机制。同时在协调者和参与者中都引入超时机制。
2、在第一阶段和第二阶段中插入一个准备阶段。保证了在最后提交阶段之前各参与节点的状态是一致的。
3PC方案:第二阶段协调者和参与者挂了,挂了的这个参与者在挂之前已经执行了操作。但是由于他挂了,没有人知道他执行了什么操作。
这种情况下,当新的协调者被选出来之后,他同样是询问所有的参与者的情况来觉得是commit还是roolback。这看上去和二阶段提交一样啊?他是怎么解决一致性问题的呢?
看上去和二阶段提交的那种数据不一致的情况的现象是一样的,但仔细分析所有参与者的状态的话就会发现其实并不一样。我们假设挂掉的那台参与者执行的操作是commit。那么其他没挂的操作者的状态应该是什么?他们的状态要么是prepare-commit要么是commit。因为3PC的第三阶段一旦有机器执行了commit,那必然第一阶段大家都是同意commit。所以,这时,新选举出来的协调者一旦发现未挂掉的参与者中有人处于commit状态或者是prepare-commit的话,那就执行commit操作。否则就执行rollback操作。这样挂掉的参与者恢复之后就能和其他机器保持数据一致性了。(为了简单的让大家理解,笔者这里简化了新选举出来的协调者执行操作的具体细节,真实情况比我描述的要复杂)
简单概括一下就是,如果挂掉的那台机器已经执行了commit,那么协调者可以从所有未挂掉的参与者的状态中分析出来,并执行commit。如果挂掉的那个参与者执行了rollback,那么协调者和其他的参与者执行的肯定也是rollback操作。
相比较2PC而言,3PC对于协调者和参与者都设置了超时时间,而2PC只有协调者才拥有超时机制。这解决了一个什么问题呢?这个优化点主要是避免了参与者在长时间无法与协调者通讯的情况下(协调者挂掉了),无法释放资源阻塞的问题。
但是相应的,正因为引入了参与者的超时机制,也导致了3PC协议在第二三阶段很容易出现数据不一致的问题。简单来说2PC是一个数据强一致性协议,而3PC通过弱化数据的一致性来解决阻塞的问题。
3PC问题
在doCommit阶段,如果参与者无法及时接收到来自协调者的doCommit或者rebort请求时,会在等待超时之后,会继续进行事务的提交。
所以,由于网络原因,协调者发送的abort响应没有及时被参与者接收到,那么参与者在等待超时之后执行了commit操作。这样就和其他接到abort命令并执行回滚的参与者之间存在数据不一致的情况。
三、分布式解决方案
1. 分布式事务解决方案之AT(Seata) 无侵入的分布式事务解决方案,适用于不希望对业务进行改造的场景,几乎0学习成本(sql都由框架托管统一执行,会存在脏写问题)
2. 分布式事务解决方案之XA XA模式一阶段不提交事务,锁定资源;AT模式一阶段直接提交,不锁定资源。XA是强一致性。
3. 分布式事务解决方案之TCC 高性能分布式事务解决方案,适用于核心系统等对性能有很高要求的场景(第一阶段会产生行锁,事务执行太久会锁行很久)
4. 分布式事务解决方案之Saga (长事务拆成短事务)
四、通过消息机制来实现
1. 分布式事务解决方案之可靠消息最终一致性
2. 分布式事务解决方案之最大努力通知