MQ消息丢失问题处理

1、MQ 介绍

MQ(Message Queue)消息队列,是基础数据结构中“先进先出”的一种数据结构。指把要传输的数据(消息)放在队列中,用队列机制来实现消息传递——生产者产生消息并把消息放入队列,然后由消费者去处理。消费者可以到指定队列拉取消息,或者订阅相应的队列,由MQ服务端给其推送消息。

2、MQ的作用

消息队列中间件是分布式系统中重要的组件,主要解决应用解耦,异步消息,流量削锋等问题,实现高性能,高可用,可伸缩和最终一致性架构。

解耦:一个业务需要多个模块共同实现,或者一条消息有多个系统需要对应处理,只需要主业务完成以后,发送一条MQ,其余模块消费MQ消息,即可实现业务,降低模块之间的耦合。

异步:主业务执行结束后从属业务通过MQ,异步执行,减低业务的响应时间,提高用户体验。

削峰:高并发情况下,业务异步处理,提供高峰期业务处理能力,避免系统瘫痪。

3、MQ的缺点

  • 系统可用性降低。依赖服务越多,服务越容易挂掉。需要考虑MQ瘫痪的情况。
  • 系统复杂性提高。需要考虑消息丢失、消息重复消费、消息传递的顺序性
  • 业务一致性。主业务和从属业务一致性的处理

4、MQ的原则

MQ传输过程中,消息数据不能多,也不能少,不能多是说消息不能重复消费;不能少,就是说不能丢失数据。如果mq传递的是非常核心的消息,支撑核心的业务,那么这种场景是一定不能丢失数据的。

5、在使用 MQ 的时候,怎么确保消息 100% 不丢失?

在分布式系统中,如果两个节点之间存在数据同步,就会带来数据一致性的问题。同理,解决的就是:消息生产端和消息消费端的消息数据一致性问题(也就是如何确保消息不丢失)。

  • 如何知道有消息丢失?
  • 哪些环节可能丢消息?
  • 如何确保消息不丢失?

首先,一条消息从生产到消费整个过程,可以分成三个阶段,分别为:消息生产阶段、消息存储阶段、消息消费阶段。

MQ消息丢失问题处理_第1张图片

  • 消息生产阶段:从消息被生产出来,然后提交给 MQ 的过程中,只要能正常收到 MQ Broker 的 ack 确认响应,就表示发送成功,所以只要处理好返回值和异常,这个阶段是不会出现消息丢失的。
  • 消息存储阶段:这个阶段一般会直接交给 MQ 消息中间件来保证,但是你要了解它的原理,比如 Broker 会做副本,保证一条消息至少同步两个节点再返回 ack
  • 消息消费阶段:消费端从Broker上拉取消息,只要消费端在收到消息后,不立即发送消费确认给 Broker,而是等到执行完业务逻辑后,再发送消费确认,也能保证消息的不丢失。

以上阶段,每个阶段都能保证消息的不丢失,但在分布式系统中,故障不可避免,作为消费生产端,我们并不能保证 MQ 是不是弄丢了你的消息,消费者是否消费了你的消息,所以,本着Design for Failure的设计原则,我们还是需要一种机制,来 Check 消息是否丢失了。

总体方案解决思路为:在消息生产端,给每个发出的消息都指定一个全局唯一 ID,或者附加一个连续递增的版本号,然后在消费端做对应的版本校验。

在生产端发送消息之前,通过拦截器将消息版本号注入消息中(版本号可以采用连续递增的 ID 生成,也可以通过分布式全局唯一 ID生成)。然后在消费端收到消息后,再通过拦截器检测版本号的连续性或消费状态,这样实现的好处是消息检测的代码不会侵入到业务代码中,可以通过单独的任务来定位丢失的消息,做进一步的排查。

这里需要你注意:如果同时存在多个消息生产端和消息消费端,通过版本号递增的方式就很难实现了,因为不能保证版本号的唯一性,此时只能通过全局唯一 ID 的方案来进行消息检测,具体的实现原理和版本号递增的方式一致。

全局唯一 ID 生成的实现方法有数据库自增主键、UUIDRedisTwitter-Snowflake 算法。

你可能感兴趣的:(消息队列,中间件)