现在最流行的就是分布式应用, 而分布式应用就要面临分布式事务的问题。现在主流的已经有四种分布式事务的解决方案。 这篇文章就是我自己的关于分布式事务的理解。
文章内容只是我自己的理解, 如果有不正确的地方欢迎各位指正。
两阶段提交需要把事务分成两步来处理, 同时还需要一个事务管理器来协调分布式事务。
第一阶段 事务管理器先发送事务指令到两个应用, 让两个应用开始事务,这时两个应用就会开始锁定资源, 准备事务,准备好后就通知到事务管理器。
事务管理器收到第一阶段的通知后,就会根据第一阶段的结果来发布第二阶段的指令
两阶段提交是强事务性, 如果是正常流程能够保证事务一致性
1.阻塞等待性能不高, 因为强事务性, 每个应用都会阻塞等待其他事务的完成, 这个阻塞就会导致效率不够。 这个很类似BIO。
单点故障问题, 如果在第一阶段完成了后, 事务管理器挂掉了后, 此时两个应用会一直阻塞等待, 事务无法完成
还是会出现事务不一致性, 如果事务管理器发送第二阶段提交是的指令,如果这个时候应用A没有收到指令(网络波动)。此时B提交了事务,A没有提交,就会导致事务不一致。
三阶段提交 是在两阶段提交的基础上进行的改进, 主要为了解决两阶段的部分缺点问题。3pc设置了超时时间的机制, 并且增加了一个阶段。
事务管理器发送准备指令到两个应用A和B, 让A和B准备事务,A和B准备好了会通知事务处理器,此流程和2pc的第一阶段的流程一样。
这个是和2PC不一样的阶段, 此时如果事务管理器收到了第一阶段准备好了指令后,就会发布第二阶段的指令,让事务A和B进行预提交操作。
预提交就是A和B收到指令开始提交事务, 并记录好事务的日志,但是不释放锁资源等,然后再返回通知给事务管理器告知预提交完成。
事务管理器收到第二阶段的指令后, 如果此时有事务预提交失败, 就会通知应用A和B取消事务, 事务开始失败。
如果第二阶段预提交全部成功后,事务管理器就会发布第三阶段指令, 提交指令。 应用A和B收到指令后就会释放锁, 事务完成。
优点:
缺点:
前面两个方案都是需要阻塞等待事务的提交, 性能不高,但是TCC提供了另外的一个思路, 就是想冻结事务需要的资源,再协调所有的应用的事务,如果所有应用都成功了就会提交事务,正常消费冻结资源, 如果有应用事务失败, 就会解冻所有冻结的资源, TCC也是需要分段的,同时也有一个事务管理器, 具体流程如下:
事务管理器发送指令到应用A和B , A和B此时就会把事务需要的资源先冻结资源, 冻结成功后就会返回通知给事务处理器。
事务失败的原因一般都是资源不够的情况, 比如扣减库存发现库存不足, 扣减金额发现金额不足等。 如果资源都冻结成功了,说明事务会成功的。
事务管理器收到第一阶段的冻结成功指令后, 此时就会发送第二阶段执: 行事务消费资源的指令。 这个时候A和B应用就会使用冻结的资源执行事务。
如果 第一阶段某个应用冻结失败后, 此时事务管理器发送 解冻资源事务失败的指令。 这个时候应用A和B就会解冻资源, 事务失败
优点:
不会阻塞其他的事务, 因为提前冻结了资源, 其他的事务就不会和他竞争资源了,自然就不会阻塞。 性能自然提高了。 性能提高就是最大的优势。
出现事务不一致的可能性低, 因为只是冻结资源, 如果此时出现问题事务协调器挂了, 此时数据还是一致性的(不会出现对不上帐的情况)。
缺点:
虽然冻结了资源不用和其他事务竞争增加了并发性,但是在本事务内部各个应用还是需要阻塞等待其他所有应用的完成的。
增加了业务的复杂度,需要程序员写大量的业务代码。
对应用的侵入性强, 不同的业务需要使用不同的 冻结解冻消费资源业务代码。 并且各个应用不能通用。
事务失败的原因有多种,此时解冻资源的操作也会复杂
比如网络波动没有收到指令, 此时可以重试解决。
比如资源不足, 此时可以释放资源,事务失败。
上面的三种事务都是为了保证分布式系统中的事务的强一致性的, 但是我们换个思路, 允许事务短时间内不一致,只要事务最终是一致性的就可以了。
而使用支持事务的MQ来实现这个思想就十分方便了, 这里推荐阿里的RocketMQ来实现。
RocketMQ现在支持了事务MQ了, 所谓的事务MQ就是指发送消息需要支持提交和回滚,如同数据库事务一样。
RocketMQ的投递确认和一直重试的特性 可以用来保证事务的最终一致性, 使用它来实现事务,十分方便, 并且各个应用完全不要阻塞,性能高效。但是会出现短暂的事务不一致。
优点:
缺点:
这个方案是完全的依赖MQ消息服务的, 而RocketMQ是独立的系统,完全可以使用各种方法来保证自己的高可用性。
完事有利就有弊, 分布式事务的四种方案都有自己的优缺点.
2PC和3PC 都是强一致性,就是使用事务协调器把单应用的事务协调到一起来完成的方案。这个方案会系统分布式的性能来确定事务的一致性,但是不用考虑回滚的复杂情况, 完全使用数据库的回滚操作。
TCC也是强一致性的, 它是换个思路的方式实现事务,他会先冻结资源, 这样就不用与其他的事务竞争公共资源,防止阻塞其他的事务,从而提高系统性能。但是它牺牲事务回滚操作的方便性和增加了冻结资源的操作
MQ消息事务 是最终一致性的, 事务类不用阻塞等待各个应用的完成,极高的提高性能。 但是它完全依赖MQ消息系统的高可用性,并且还要写复杂的回滚业务。