RabbitMQ经典三问

RabbitMQ如何保证消息不会丢失?

可能会造成消息丢失的原因

  • 生产者方面,当生产者发送消息到 Broker 时,由于网络问题或者自身问题没有达到
  • 消息到达Broker,但是当 Broker 持久化的时候,RabbitMQ宕机
  • 消费者方面,消费者在接收消息时,出现宕机或者自身服务问题导致消息没收到

解决方法

  • 生产端要做 confirm 机制, 当消息发送给 Broker 时,Broker都要告诉生产者。如果失败了,可以将失败的消息保存到数据库中,采用定期扫描的方式尝试重新推送。
  • 消费端要做 手动ack 机制,当消费者消费成功之后,要告诉RabbitMQ删除队列中的消息。
    • 这样可能还存在一个问题,就是消费端返回 ack 时,突然宕机,由于消费者消费完了,但是队列中的消息还存在,就有可能造成 重复消费 的问题

RabbitMQ 如何避免重复消费?

造成重复消费的原因

  • 生产者:重复推送一条数据,比如:多次调用 Controller 接口,没有做接口幂等性导致
  • MQ端:消费者消费成功,响应 ack 时,MQ挂掉了,导致MQ认为还未消费这条数据,当MQ恢复后,继续推送这条数据导致重复消费
  • 消费端:消费者消费完,正准备响应 ack 时,消费者挂掉了 ,消费者恢复之后,MQ仍然认为没有消费成功。

解决方法

  • 使用数据库唯一约束

但是它局限性比较大,仅能在数据库新增时生效,并且性能较低

  • 在生产端将接口设计成幂等性, 防止重复推送同一条数据
  • 使用防重表(Redis/MySQL), 插入消费记录

当消费者开始消费的时候,先在防重表 中插入一条记录,记录当前记录的状态为消费中

  • 如果能插入成功,说明这条消息还没有消费过,去正常执行业务代码即可。
    • 当业务代码执行失败时,将该条记录在 防重表 中删除,继续重试
  • 如果插入失败,说明这条消息正在消费中或者已经消费过,但是由于某些原因导致未删除记录。
    • 此时在判断这条消息是否已经消费过,消费过则返回成功结束,没有消费过,可以利用延时队列进行重试!

可以利用Redis防重表 中插入一条记录时,设置一个过期时间,为了避免在执行完业务代码、更新业务状态时出现异常而导致重复消费。

并且还可以记录一个 消费次数 的字段 , 当一条消息被多次消费 仍然不成功时,可以记录到日志中,由具体的开发人员分析到底是什么原因,具体分析!

RabbitMQ如何解决消息堆积问题?

产生消息堆积的原因

  • 消费者宕机积压

  • 消费者消费能力不足积压

  • 发送者发送流量太大

解决方法

  • 简化消费者的逻辑,减少耗时,提高消费速度
  • 如果存在无法处理的消息,使用死信队列,防止堵塞
  • 上线更多的消费者,进行正常消费
相关推荐
麦兜*4 小时前
深入解析现代分布式事务架构:基于Seata Saga模式与TCC模式实现金融级高可用与数据最终一致性的工程实践全解析
分布式·金融·架构
難釋懷4 小时前
分布式锁-redission功能介绍
分布式
only-qi7 小时前
微服务场景下,如何实现分布式事务来保证一致性?
分布式·微服务·架构
m0_564876848 小时前
Distributed data parallel (DDP)分布式训练
分布式
BYSJMG10 小时前
计算机毕设选题推荐:基于Hadoop的交通事故数据可视化分析系统
大数据·vue.js·hadoop·分布式·后端·信息可视化·课程设计
野犬寒鸦10 小时前
从零起步学习并发编程 || 第三章:JMM(Java内存模型)详解及对比剖析
java·服务器·开发语言·分布式·后端·学习·spring
虫小宝11 小时前
查券返利机器人的异步任务调度:Java XXL-Job+Redis实现海量查券请求的分布式任务分发
java·redis·分布式
yq19820430115613 小时前
构建高可用资源导航平台:基于Django+Scrapy的分布式架构实践
分布式·scrapy·django
你这个代码我看不懂13 小时前
Kafka常见问题解答
分布式·kafka
Tony Bai13 小时前
Git 即数据库:Beads (bd) —— 专为 AI Agent 打造的分布式任务追踪引擎
数据库·人工智能·分布式·git