什么是分布式事务
一次大操作由不同的小操作组成,这些小操作在不同的服务器上,且属于不同的应用,分布式事务要保证这些小操作要么全部成功,要么全部失败。
CAP
CAP
- C(一致性)(Consistence)不同节点的数据一致。
- A(可用性)(Availability)节点故障,可在合理的时间进行合理的响应。
- P(分区容错性)(Partition Tolerance)集群中某台机器出现了问题,这个集群仍能正常工作。
架构
- CA:问题:分区后,为了保证一致性A,必须拒绝请求,而拒绝请求又违反可用性C。
- CP:强一致性(例如:zk)
- AP:追求分区容错和可用性
- BASE: Basically Available(基本可用)、Soft state(软状态)和 Eventually consistent (最终一致性)
分布式事务解决方案
是否需要分布式事务
分布式事务一般是由于微服务过多,又需要保证一个大操作里多个服务全部成功。
但是一般如果要使用分布式事务,我认为应该先看一下项目架构,不要盲目使用,不然容易过度设计,导致维护成本急剧上升
。比如有些团队项目微服务拆分不合理,或者是过度设计拆分过多,一个人负责很多微服务,导致很多业务都要分布式事务,这种情况我认为应该先把需要分类聚合服务,使用数据库的本地事务。
因为不论任何一种方案都会增加复杂度,不要因为追求某些设计,而引入不必要的成本和复杂度。
微服务环境下的困境
如果使用了es,图数据库,NOSQL之类,就不太适合使用分布式事务。比较难以回退。
2PC
正常流程
异常流程
-
事务询问prepare:协调者向所有的参与者发送事务预处理请求。
-
执行本地事务:各个参与者节点执行本地事务,但不提交。
-
事务响应:各个参与者向协调者反馈响应(yes或no)
-
提交/执行:
-
协调者都是yes:事务提交
-
协调者有no:事务回滚
2PC缺点
-
性能问题:无论第一阶段还是第二阶段,所有参与者都有可能被锁住。只有当所有节点准备完毕才会通知全局提交。参与者提交本地事务后才会释放资源,对性能影响大。
-
单点故障:一旦协调者故障,参与者会一致阻塞。虽然可以重新选举一个协调者,但无法解决参与者阻塞问题。
-
参与者宕机:超时机制来处理,超时发送终止事务请求。
-
协调者宕机:引入协调者备份,同时协调者记录操作日志,协调者备份成为主机后,并读取操作日志。
-
参与者和协调者都宕机:重选协调者,重新执行第一第二步骤(此方案不完善)
-
数据不一致:比如协调者发送了commit操作,部分参与者没有收到通知,处于阻塞状态,就会导致数据不一致。
3PC
- CanCommit 尝试获取数据库锁,如果可以返回yes
- PreCommit 执行事务操作
- DoCommit 提交
三阶段提交主要是为了解决两阶段提交协议的阻塞问题,而且一定程度上减少了数据不一致的可能。
在一阶段投票通过后,二阶段都是preCommit的情况下有理由相信事务可提交的概率比较大。
但是3pc仍然不能解决数据一致性问题,比如协调者发出回滚命令,但是由于网络问题,参与者在等待时间内未接收到自动commit,而其他事务进行了回滚,造成数据不一致。
TCC(补偿事务)
-
Try:
-
尝试执行,完成所有业务检查(一致性)
-
预留必须业务资源(准隔离性)
-
Confirm
-
真正执行业务
-
Confirm操作要满足幂等性
-
Cancel
-
释放Try阶段预留的业务资源
-
Cancel操作满足幂等性
- 采用中间态
- 应用侵入性强,从业务需要提供TCC业务操作,需要try,confirm,cancel代码
- 业务协调者控制业务活动的一致性
-
优点
-
强隔离性,强一致性
-
适合执行时间短的业务
-
缺点
-
应用侵入性强
3PC对比2PC
-
2PC
-
延迟低,但是参与者故障后会阻塞。
-
3PC
-
多了一次确认,参与者也引入超时机制,可用性高,但是可能会导致数据不一致,并且延迟变高。
- 我们可以发现
3PC使用超时自动提交
的方式解决了2PC中无法判断状态需要不断等待的情况
,也就是提升了服务可用性。但是3PC比2PC多了一个步骤,所以延时应该是增加了。同时3PC可能存在网络分化情况,也就是协调者在第二阶段发送了PREPARE消息后,如果在第三阶段发送ABORT消息,则如果网络出现问题,导致消息部分节点未送达,就会出现某些节点ABORT了,某些节点COMMIT了。 - 也就是说,3PC实际并没有解决2PC中的那种协调者和参与者同时宕机的场景,只是做了自动提交,来提升服务可用性。
- 那2PC能否做自动提交呢?2PC由于只有2个阶段,第一阶段就已经执行对应的操作了(锁资源),如果没有收到第二阶段的COMMIT请求就自动提交,那连一次跟其他节点确认的机会都没有,这样出错的可能性很大。3PC至少是经过第一轮跟其他节点确认后,才会进行超时自动提交的,降低了出错概率。
- 综上,2PC延迟低,但是参与者故障后可能会阻塞;3PC可用性高,但可能出现数据不一致(网络分化),以及多了个步骤导致延迟会高一些。
本地消息表
此方案的核心是将分布式处理的任务通过消息日志的方式来异步执行,可以通过定时轮询或者人工重试,保证事务的最终一致性,这是BASE理论
。
MQ事务
实际上就是对本地消息表做了一个封装,将本地消息表移动到了mq内,通过mq失败不断重试,消费端保证幂等,最终由定时任务兜底保证。
SAGA事务
将长事务分解成多个短事务,每个子事务由数据库保持一致性,如果有失败,依次调用调用补偿函数。