阅读本文大概需要 8.4 分钟。
一 分布式系统特点
一致性:分布式环境下多个节点的数据是否强一致。 可用性:分布式服务能一直保证可用状态。当用户发出一个请求后,服务能在有限时间内返回结果。 分区容忍性:特指对网络分区的容忍性。
基本可用(Basically Available):指分布式系统在出现故障时,允许损失部分的可用性来保证核心可用。 软状态(Soft State):指允许分布式系统存在中间状态,该中间状态不会影响到系统的整体可用性。 最终一致性(Eventual Consistency):指分布式系统中的所有副本数据经过一定时间后,最终能够达到一致的状态。
二 一致性模型
强一致性:数据更新成功后,任意时刻所有副本中的数据都是一致的,一般采用同步的方式实现。 弱一致性:数据更新成功后,系统不承诺立即可以读到最新写入的值,也不承诺具体多久之后可以读到。 最终一致性:弱一致性的一种形式,数据更新成功后,系统不承诺立即可以返回最新写入的值,但是保证最终会返回上一次更新操作的值。
三 分布式事务
协调者会问所有的参与者结点,是否可以执行提交操作。 各个参与者开始事务执行的准备工作:如:为资源上锁,预留资源。 参与者响应协调者,如果事务的准备工作成功,则回应“可以提交”,否则回应“拒绝提交”。
如果所有的参与者都回应“可以提交”,那么,协调者向所有的参与者发送“正式提交”的命令。参与者完成正式提交,并释放所有资源,然后回应“完成”,协调者收集各结点的“完成”回应后结束这个Global Transaction。 如果有一个参与者回应“拒绝提交”,那么,协调者向所有的参与者发送“回滚操作”,并释放所有资源,然后回应“回滚完成”,协调者收集各结点的“回滚”回应后,取消这个Global Transaction。
所有的操作必须是事务性资源(比如数据库、消息队列、EJB组件等),存在使用局限性(微服务架构下多数使用HTTP协议),比较适合传统的单体应用; 由于是强一致性,资源需要在事务内部等待,性能影响较大,吞吐率不高,不适合高并发与高性能的业务场景;
Try:完成所有业务检查,预留必须业务资源。 Confirm:真正执行业务,不作任何业务检查;只使用Try阶段预留的业务资源;Confirm操作满足幂等性。 Cancel:释放Try阶段预留的业务资源;Cancel操作满足幂等性。
位于业务服务层而非资源层。 没有单独的准备(prepare)阶段,Try操作兼备资源操作与准备能力。 Try操作可以灵活选择业务资源的锁定粒度。 开发成本较高。
Canfirm和Cancel的幂等性很难保证。 这种方式缺点比较多,通常在复杂场景下是不推荐使用的,除非是非常简单的场景,非常容易提供回滚Cancel,而且依赖的服务也非常少的情况。 这种实现方式会造成代码量庞大,耦合性高。而且非常有局限性,因为有很多的业务是无法很简单的实现回滚的,如果串行的服务很多,回滚的成本实在太高。
基于事务消息的方案 基于本地消息的方案
事务发起者预先发送一个事务消息。 MQ 系统收到事务消息后,将消息持久化,消息的状态是“待发送”,并给发送者一个 ACK 消息。 事务发起者如果没有收到 ACK 消息,则取消本地事务的执行;如果收到了 ACK 消息,则执行本地事务,并给 MQ 系统再发送一个消息,通知本地事务的执行情况。 MQ 系统收到消息通知后,根据本地事务的执行情况更改事务消息的状态,如果成功执行,则将消息更改为“可消费”并择机下发给订阅者;如果事务执行失败,则删除该事务消息。 本地事务执行完毕后,发给 MQ 的通知消息有可能丢失了。所以支持事务消息的 MQ 系统有一个定时扫描逻辑,扫描出状态仍然是“待发送”状态的消息,并向消息的发送方发起询问,询问这条事务消息的最终状态如何并根据结果更新事务消息的状态。因此事务的发起方需要给 MQ 系统提供一个事务消息状态查询接口。 如果事务消息的状态是“可发送”,则 MQ 系统向下游参与者推送消息,推送失败会不停重试。 下游参与者收到消息后,执行本地事务,本地事务如果执行成功,则给 MQ 系统发送 ACK 消息;如果执行失败,则不发送 ACK 消息,MQ 系统会持续推送给消息。
事务的发起方维护一个本地消息表,业务执行和本地消息表的执行处在同一个本地事务中。业务执行成功,则同时记录一条“待发送”状态的消息到本地消息表中。 系统中启动一个定时任务定时扫描本地消息表中状态为“待发送”的记录,并将其发送到 MQ 系统中,如果发送失败或者超时,则一直发送,直到发送成功后,从本地消息表中删除该记录(或修改状态为“已发送”)。 消息会重试发送,可能会重复,所以每条消息需要一个唯一ID。
后续的消息订阅者从MQ消费消息,进行下游的本地事务操作。 为了避免消息重复消费,下游服务可以维护一个本地的“消息记录表”记录已经处理消费过的消息,每次处理消息前通过该表检查消息是否消费过。
推荐阅读:
亲身经历:一个00后的中专生是怎么在深圳拿到15K(Java后端开发)
StackOverflow 上面最流行的 7 个 Java 问题!
微信扫描二维码,关注我的公众号
朕已阅
文章收集整理于网络,请勿商用,仅供个人学习使用,如有侵权,请联系作者删除,如若转载,请注明出处:http://www.cxyroad.com/1651.html