微服务架构的分布式事务解决方案(3)--消息发送一致性(可靠消息的前提保证)

我们之前的服务间消息传递是主动方应用直接发送给被动大应用
在这里插入图片描述
但是这种通讯方式其实并不是很好,耦合性高,不稳定,效率差。因此我们有了消息中间件,使用消息中间件可以更好的在分布式系统中实现服务间通讯。
在这里插入图片描述
消息中间件在分布式系统中的主要作用是:
异步通讯,解耦,并发缓冲

  • 消息发送和投递的不可靠性

但是这种通信方式也有可能不稳定,有着消息发送和投递的不可靠性
在这里插入图片描述
如上图所示,可能由于网络的原因 ,消息中间件失败,主动方应用或者被动方应用失败,导致消息的不可靠性。

在分布式的部署环境下,需要通过网络进行通讯,就引入了数据传输的不确定性。
也就是CAP理论中的P,分区容错性的问题。

  • 消息发送一致性

消息发送一致性指的是产生消息的业务动作与消息发送的一致。
也就是说,如果业务操作成功,那么由这个业务操作所产生的消息一定要成功的投递出去,否则就丢失消息。
换言之,就是业务操作成功,消息系统就应该发送消息;业务操作失败,消息系统就不应该发送消息。

  • 如何保证消息发送的一致性呢?

实现JMS标准中的XA协议(基于两阶段协议)虽然可以保证发送的一致性,引入全局事务型接口,支持分布式事务,但是引入XA,违背了柔性事务的初衷。

因此我们有了下面的变通的做法
在这里插入图片描述
具体的做法:
(1)主动方应用先把消息发给消息中间件,消息状态标记为“待确认”
(2)消息中间件接收到消息后,把消息持久化到消息存储中,但并不向被动方应用投递消息。
(3)消息中间件返回消息持久化的结果(成功/失败),主动方根据返回的结果进行业务操作

  • 若消息中间件返回的结果是失败,则主业务方放弃执行业务。结束
  • 若消息中间件返回的结果是成功,则主业务方继续执行业务操作。

(4)主动方的业务操作完成之后,把业务操作结果(成功/失败)发送给消息的中间件
(5)消息中间件收到业务操作结果后,根据业务结果进行处理

  • 若业务方发送过来的数据是失败,则删除消息存储中的消息,结束
  • 若业务方发送过来的数据是成功,则更新消息中间件,将其消息存储中的消息状态改变为"待发送",紧接着执行消息投递,向被动方发送消息。

(6)前面的正向流程都成功后,向被动方应用投递消息。

但是如果其中任何一个节点除了问题呢?

在这里插入图片描述
(1)从主动方应用的角度来进行分析:

  • 主动方应用预发送消息失败
    消息未进行存储,业务操作也没有执行(因为没有收到消息中间件传来的成功的消息),可能导致的原因是主动方应用,网络,消息中间件,消息的存储失败。
    该消息发送也是一致性的。因为即没有进行消息的存储,也没有执行业务代码。

  • 主动方应用向消息中间件发送消息,主动方没有收到消息的存储结果
    可能导致该现象的原因是:
    a> 消息未进行存储,业务操作未执行,该消息一致性是一致的,业务没执行,消息没存储。
    b> 消息已经存储,但是业务没有执行,这有可能是网络的原因,导致消息中间件发送给服务端失败,该消息发送一致性就是不一致的,因为消息已经进行了存储,但是业务操作无法执行。

  • 主动方应用收到消息中间件发送的成功的结果,但是未执行业务操作就失败了
    该现象发生的原因是主动方执行其业务代码时候出错,导致执行失败,该结果就不满足一致性,因为消息已经进行了存储,但是主动方没有执行其业务代码。

(2)从消息中间件的角度来进行分析

  • 消息中间件没有收到主动方应用的业务操作结果(等待主动方业务方法执行的结果)
    a> 消息已经进行存储(待确认状态),业务方法没有执行,或者执行出错进行回滚
    b> 消息已经进行存储(待确认状态),业务方法已经执行,并且执行成功,但是网络等原因导致消息中间件没有收到。
    上面的两种情况都是不满足一致性的,因为消息的状态并未改变成已确认或者可发送。

  • 消息中间件收到业务操作的结果(成功/失败),但是处理消息存储中的消息状态是失败的
    a> 消息已经进行了存储(待确认),业务操作未执行,或者业务执行操作出错回滚。
    b> 消息已经进行了存储(待确认),业务操作成功
    上面的两种情况都是不满足一致性的,因为消息的状态并未改变成已确认或者可发送。和上面情况一致。

异常情况总结
异常情况 一致性 异常处理方法
消息未进行存储,业务操作未执行 一致
消息已经进行存储(状态待确认),业务操作未执行 不一致 确认业务操作结果,处理结果(删除消息中间件中的对应消息)
消息已经进行存储(状态待确认),业务操作成功,但是消息中间件未收到主动方的业务执行结果 不一致 确认业务操作结果,处理消息(更新消息的状态,执行消息的投递)
消息发送的一致性的异常处理

在这里插入图片描述
如果消息中间件和业务操作出现不一致的状况,我们提供了消息中间件对主动方业务的查询功能,我们可以在主动方查询出来消息中间件中消息状态是“待确认”的消息状态,然后判断其对应的业务操作的结果,若成功,将消息中间件的状态改变,直接进行消息的投递,若失败,则删除消息中间件中存储的消息。

重要

我们在这里强调一点,我们所说的消息发送的一致性,指的是主动方和消息中间件之间的关系,并不是保证消息中间件到被动方之间的消息一致。

猜你喜欢

转载自blog.csdn.net/u014437791/article/details/89344959