读书笔记-微服务分布式事务-03
1 分布式事务基础
1.1 CAP
https://www.jianshu.com/p/2f6bd7da9c9a
需要注意的:
- CAP中的C指的是强一致性
- CAP建立在没有网络延迟的基础上,当事务提交的时候,从A节点复制到B节点忽略了网络延迟,但是现实中肯定有一段时间的不一致。
1.2 BASE
BASE 是 Basically Available(基本可用)、Soft state(软状态)和 Eventually consistent (最终一致性)三个短语的缩写。是对CAP中AP的一个扩展
- 基本可用:分布式系统在出现故障时,允许损失部分可用功能,保证核心功能可用。
- 软状态:允许系统中存在中间状态,这个状态不影响系统可用性,这里指的是CAP中的不一致。
- 最终一致:最终一致是指经过一段时间后,所有节点数据都将会达到一致。
BASE解决了CAP中理论没有网络延迟,在BASE中用软状态和最终一致,保证了延迟后的一致性。BASE和 ACID 是相反的,它完全不同于ACID的强一致性模型,而是通过牺牲强一致性来获得可用性,并允许数据在一段时间内是不一致的,但最终达到一致状态。
2 分布式事务
下面是几种常见的方案(参考:https://blog.csdn.net/bjweimengshu/article/details/86698036
)
2.1 2PC
简单来说,是将事务的提交操作分成了prepare和commit两部分。代表2pc分布式事务的有XA Transactions,XA分为两阶段:
第一阶段:
发起方向协调者发送请求,协调者首先会分别向参与节点发送prepare请求,问一下这些节点能不能处理成功了,此时这些参与者一般会开始执行本地事务,但是执行完后并不会立马提交,而是返回结果代表已经就绪。
第二阶段:正常
如果都返回可以处理,那么协调者就会向所有参与者发送commit,此时参与者就可以提交本地事务了,最终协调者返回ack给业务方,代表分布式事务成功。
第二阶段:异常
如果有节点反馈不能执行事务,此时协调者会发送rollback消息,通知各个参与者回滚,释放资源,并向业务方返回分布式事务处理失败结果
2.1.1 优点
- 实现成本低,数据库已经实现
2.1.2 缺点
- 单点问题:如果事务管理器在第一阶段已经完成,第二阶段未提交时宕机,资源管理器将一直阻塞无法使用
- 性能问题:整个流程,节点都要占用数据库资源。
- 数据不一致:2pc虽然是分布式数据强一致的解决方案,但是仍可能出现数据不一致的可能。例如在第二阶段,协调者发出commit同志,但是由于 网络原因部分节点没有收到通知而一直阻塞,就产生了数据不一致的可能。
2.2 TCC
本文将了解一个跟2pc很像的事务提交协议,tcc事务提交协议,全称是:try-confirm-cancel,也是一个分为两个阶段的事务提交协议,如图所示
imagetcc事务提交协议分为两个阶段:
-
阶段一,主业务尝试(try)调用从业务,从业务并不直接执行,而是进行一个预留操作。比如,扣减库存问题,并不直接扣减库存,而是预留一个扣减字段,表示要扣减多少库存。
-
阶段二,在从业务都返回yes的情况下,主业务将会确认(confirm)之前的预留操作,也就是会根据之前的扣减字段直接扣减库存了。那如果不是全部yes的情况下,就会调用取消(cancel)请求,取消之前的扣减字段。如果confirm/cancel失败,会根据活动日志重试,保证最终一致性。
2.2.1 tcc与2pc有什么区别
tcc的过程和2pc非常像,一阶段prepare,二阶段confirm/cancel,但是还是有很大的不同的。
- 开发者感知:
2pc的两个阶段对开发人员是没有感知的,开发人员仍对资源进行单一的更新操作。而tcc的try-confirm-cancel需要开发人员提供一个业务逻辑来维护事务提交,也就是业务入侵。
- 强一致性和最终一致性:
两阶段提交(2PC)是一种强一致性分布式事务算法,这里的强一致性是一种相对的说法,是相对于柔性事务算法(遵循BASE理论),如TCC,Saga这类满足最终一致性算法而言。2PC基本满足事务的ACID特性。
2.3 可靠消息最终一致性
消息发送一致性:是指产生消息的业务动作与消息发送的一致。也就是说,如果业务操作成功,那么由这个业务操作所产生的消息一定要成功投递出去(一般是发送到kafka、rocketmq、rabbitmq等消息中间件中),否则就丢消息。
如何实现数据库操作和消息发送的一致性?有两种方案:一种是基于MQ的事务消息,另一种是
事务消息的逻辑,由发送端 Producer进行保证(消费端无需考虑)
-
首先,发送一个事务消息,这个时候,mq将消息状态标记为Prepared,注意此时这条消息消费者是无法消费到的。
-
接着,执行业务代码逻辑,可能是一个本地数据库事务操作
-
最后,确认发送消息,这个时候,mq将消息状态标记为可消费,这个时候消费者,才能真正的保证消费到这条数据。
-
如果确认消息发送失败了怎么办?mq会定期扫描消息集群中的事务消息,如果发现了Prepared消息,它会向消息发送端(生产者)确认。mq会根据发送端设置的策略来决定是回滚还是继续发送确认消息。这样就保证了消息发送与本地事务同时成功或同时失败。
如果消费失败怎么办?人工解决。