[准备面试|MQ] MQ消息如何保证不丢失

179 阅读2分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第24天,点击查看活动详情

MQ 的使用场景

单机应用时将所有的功能都聚集在一个项目里面,但是在后面业务体量不断扩大,开始采用微服务设计思想,拆分服务。随着业务场景的复杂增加,可能需要引入消息队列中间件来解决一下场景:

  • 异步:部分业务对数据一致性要求不高的场景,且非实时一致性时,可以异步处理。比如场景:商城的支付功能
  • 解耦:部分业务耦合性过高提高系统的复杂度,通过MQ接口业务系统。比如订单系统中下单成功后通知库存系统
  • 削峰:偶尔高峰期时流量很大,服务器,redis ,mysql 承受能力不同。为了保证服务的高可用,加入 MQ 控制请求。比如:秒杀系统、商城中的抢购活动

MQ 消息丢失

MQ 消息经历三个过程从生产,到MQ 中间件中,再到被消费。在这个过程中,如何保证消息 100% 不丢失?

  • 从生产消息到 push 到消息队列之前,只要能够正常收到 MQ 的 ack 确认响应基本确认发送成功。一般该阶段不会出现消息丢失情况。除非因业务逻辑问题出现投递失败,可通过捕获方式将要发送消息记录起来
  • 消息在消息队列中时,有中间件 MQ 保证其不丢失。比如使用 Kafka,多节点,保证一条消息至少被同步到两个节点再返回 ack
  • 消息被消费阶段,拉取到消息一般非异常情况都能正常消费。若出现问题时可增加反馈机制,即完成消费后再发送消费确认。Check 机制检查消息是否被消费。

Check 机制:每个消息都带有唯一ID ,且ID 都是连续递增的,然后再消费端接收到消息后通过拦截检测版本号的连续性或者消费状态检验消息是否被消费。

MQ 消息重复

消息消费时出现失败时,经常会通过补偿机制重新发送,重试过程中产生重复消息时怎么解决?

在数据库或者 Redis 中记录消息日志,要进行业务处理前先验证消息是否已被消费,如果已经被消费了就停止执行业务处理,否则继续执行。

MQ 消息积压

有时候因为消费服务问题,导致消息积压在 MQ 中。

  • 如果是线上问题,可以优先通过扩容或者降级承担流量。
  • 如果是服务业务逻辑处理问题,需要排查问题并解决问题