RabbitMq分布式事务解决方案第一篇

前言

微服务架构下,相比单机事务,一个比较复杂的地方在于,在分布式环境下,面对的是分布式事务,分布式事务整体来说无法严格遵循传统的ACID4个特性,而只能根据系统的业务指标,通常满足可用性,和最终一致性,这也是不少互联网产品的实践结果的选择

分布式事务一章中,探讨了有关常用分布式事务的几种解决方案,可以依据自己所在项目的特点,有选择的使用,比如对数据的一致性要求严格而对并发数可容忍的,可以考虑使用seata解决,对并发要求高,同时对数据一致性的要求也比较高的,可以考虑使用rocketMq事务消息

下面要介绍的是使用rabbitMq如何解决分布式事务

在分布式事务解决方案中,提到了一种思路,叫做柔性事务解决方案,柔性在这里的含义可以理解为尽最大可能满足数据的最终一致性,它结合了“最大努力通知”模型的精髓,同时由于消息中间件的高并发能力,在某些场景下,可以大提升分布式系统的整体效能

rocketMq事务解决方案中,使用rocketMq提供的事务消息,是可以达到预期的目的的,但研究过rocketMq源码或者对其框架比较熟悉的同学应该知道,事务消息在rocketMq中是比较耗费性能的一种

为什么采用rabbitMq

关于rabbitMq的介绍,这里不再多做介绍,有兴趣的同学可以参阅rabitmq专栏进行学习或者上网查阅相关资料

总结来说,rabbitMq提供了相当丰富和完善的消息处理机制和基于消息的各自回调事件,用于满足开发者在消息传递过程中方便的拿到消息的各种状态,从而根据消息的各种状态指导应用上下文的业务走向

下图是一张rabbitMq在分布式环境下,从应用A发消息到应用B接收消息时,消息在rabbitMq内部的一个传递的过程
在这里插入图片描述

一个正常的消息流程是,应用A发消息到rabbitMq,mq接收到消息之后,如果应用A发送至mq成功,应用A内部可以通过confirmCallBack的回调函数掌握消息是否投递成功,MQ接收到消息之后,会按照预定好的规则,将这条消息分发到指定的exchange,exchange再根据routingKey将消息投递到与之绑定的queue中

如果MQ在将消息发出去的时候没有找到与之绑定的队列,比如queue没有创建,就会将消息退回,这种情况下,对于应用A来说,可以通过returnCallBack的回调函数掌握退回消息的情况

如果MQ成功将消息通过exchange投递到指定的queue中,且被应用B正常消费,且应用B确认消费成功后,MQ就会删掉queue中的这条消息

以上描述的是一个正常的消息消费过程,而在实际开发过程中,情况可能会更加复杂,比如应用A发消息至MQ时网络问题,或者MQ服务器宕机了,或者应用B消费消息时候宕机,或者没有及时确认等等

如何与业务应用结合

既然要使用rabbitMq作为分布式事务的解决方案,我们可能需要考虑下面几个问题

  • MQ在业务应用中扮演什么角色
  • 是否需要存储消息数据
  • MQ如何保证业务应用的事务最终一致性
  • 要使用到MQ的哪些关键特性

如果将rabbitMq作为一个应用层框架级的中间件进行使用,上面几个问题是必须要考虑的,小编从自身业务中的应用以及思考总结,可以充分利用rabbitMq提供的各种消息回调机制,封装并完善消息从发送、接收、确认等过程,即从框架层面的封装上思考如何将rabbitMq运用到自己的业务中

结合上面的消息传递业务流程图,其中几个比较重要的点如下

  • MQ是与本地事务的关系,互相依赖,MQ消息发送失败,本地事务亦失败
  • 事务的传递依赖消息在MQ中的传递,因此MQ消息需要持久化
  • 考虑到在生产中,消息的量级会非常大,消息一旦成功发送到MQ,生产端需要删除消息,生产端通过confirmCallBack回调机制,判定消息是否成功发送至MQ
  • MQ将消息发送至指定应用,未能投递成功,通过ReturnCallback得到消息退回的通知,退回的消息将重新持久化,并通过定时任务尝试多次发送(多次发送仍然无效,消息将进入死信队列,做后续业务处理)
  • 消费端应用消费成功并ACK之后,删除消息

上面的流程图展示了一个消息从投递到成功的完整路径,为了更好的完善我们的逻辑,以及在实际业务场景中预判到的几个失败场景,主要包括生产端应用的发送失败的重试,以及消费端的消费失败重试

发送失败重试

在这里插入图片描述

在上面的流程中,为了清楚的记录消息从应用到MQ之间的投递状态,即围绕是否成功发送到MQ被MQ接收来展开,其中比较关键的需要一张消息表,利用这个消息表来传递,具体来说,消息表在设计中为了具备较强的灵活性,建议与应用的某个或者某些关键的业务字段结合,方便消息回溯

以上是消息从应用到达MQ过程涉及到几个关键的流程分析

消费失败流程分析

在这里插入图片描述
消费端的流程和生产端的流程类似,一旦接收到消息之后,首先需要进行消息的持久化,但这里可能存在第一次消费失败的情况,一旦消费失败了,通过本地消息表可以触发再次的消费,消费次数达到预设的阈值时,根据业务的需要,将这些无法消费的消息推送至死信队列,等待后面的业务处理,或者达到最大次数时发送告警通知等

猜你喜欢

转载自blog.csdn.net/zhangcongyi420/article/details/114479019