当前位置: 首页 > news >正文

面试题-----RabbitMQ

如何保证消息不丢失?

场景

消息发送过程

发送者

生产者确认机制


RabbitMQ 提供了 publisher confirm 机制来避免消息发送到 MQ 过程中丢失。消息发送到 MQ 以后,会返回一个结果给发送者,表示消息是否处理成功

消息持久化

MQ 默认是内存存储消息,开启持久化功能可以确保缓存在 MQ 中的消息不丢失。

消费者确认

RabbitMQ 支持消费者确认机制,即:消费者处理消息后可以向 MQ 发送 ack 回执,MQ 收到 ack 回执后才会删除该消息 。而 SpringAMQP 则允许配置三种确认模式:

  • manual:手动 ack,需要在业务代码结束后,调用 api 发送 ack。
  • auto:自动 ack,由 spring 监测 listener 代码是否出现异常,没有异常则返回 ack;抛出异常则返回 nack
  • none:关闭 ack,MQ 假定消费者获取消息后会成功处理,因此消息投递后立即被删除

回答

嗯!我们当时 MYSQL 和 Redis 的数据双写一致性就是采用 RabbitMQ 实现同步的,这里面就要求了消息的高可用性,我们要保证消息的不丢失。主要从三个层面考虑
第一个是开启生产者确认机制,确保生产者的消息能到达队列,如果报错可以先记录到日志中,再去修复数据
第二个是开启持久化功能,确保消息未消费前在队列中不会丢失,其中的交换机、队列、和消息都要做持久化
第三个是开启消费者确认机制为 auto,由 spring 确认消息处理成功后完成 ack,当然也需要设置一定的重试次数,我们当时设置了 3 次,如果重试 3 次还没有收到消息,就将失败后的消息投递到异常交换机,交由人工处理

消息的重复消费问题如何解决的?

回答

嗯,这个我们还真遇到过,是这样的,我们当时消费者是设置了自动确认机制,当服务还没来得及给 MQ 确认的时候,服务宕机了,导致服务重启之后,又消费了一次消息。这样就重复消费了
因为我们当时处理的支付(订单 | 业务唯一标识),它有一个业务的唯一标识,我们再处理消息时,先到数据库查询一下,这个数据是否存在,如果不存在,说明没有处理过,这个时候就可以正常处理这个消息了。如果已经存在这个数据了,就说明消息重复消费了,我们就不需要再消费了
其实这个就是典型的幂等的问题,比如,redis 分布式锁、数据库的锁都是可以的

RabbitMQ 中死信交换机?(RabbitMQ 延迟队列有了解过嘛)

死信交换机

当一个队列中的消息满足下列情况之一时,可以成为死信(dead letter):

  • 消费者使用 basic.reject 或 basic.nack 声明消费失败,并且消息的 requeue 参数设置为 false
  • 消息是一个过期消息,超时无人消费
  • 要投递的队列消息堆积满了,最早的消息可能成为死信

如果该队列配置了 dead-letter-exchange 属性,指定了一个交换机,那么队列中的死信就会投递到这个交换机中,而这个交换机称为死信交换机(Dead Letter Exchange,简称 DLX)。

TTL

TTL,也就是 Time-To-Live。如果一个队列中的消息 TTL 结束仍未消费,则会变为死信,ttl 超时分为两种情况:

  • 消息所在的队列设置了存活时间
  • 消息本身设置了存活时间

 public void sendTtlMessage() {// 创建消息,设置消息体和 TTL(单位:毫秒)Message message = MessageBuilder.withBody("hello, ttl message".getBytes(StandardCharsets.UTF_8)).setExpiration("5000")  // 设置消息的存活时间为 5000 毫秒(5 秒).build();// 消息 ID,需要封装到 CorrelationData 中,用于确认机制等场景CorrelationData correlationData = new CorrelationData(UUID.randomUUID().toString());// 发送消息到指定交换机和路由键rabbitTemplate.convertAndSend("ttl.direct", "ttl", message, correlationData);}

延迟消息插件

回答

我们当时的 xx 项目有一个 xx 业务,需要用到延迟队列,其中就是使用 RabbitMQ 来实现的。
延迟队列就是用到了死信交换机和 TTL(消息存活时间)实现的。
如果消息超时未消费就会变成死信,在 RabbitMQ 中如果消息成为死信,队列可以绑定一个死信交换机,在死信交换机上可以绑定其他队列,在我们发消息的时候可以按照需求指定 TTL 的时间,这样就实现了延迟队列的功能了。
我记得 RabbitMQ 还有一种方式可以实现延迟队列,在 RabbitMQ 中安装一个死信插件,这样更方便一些,我们只需要在声明交互机的时候,指定这个就是死信交换机,然后在发送消息的时候直接指定超时时间就行了,相对于死信交换机 + TTL 要省略了一些步骤

RabbitMQ如果有100万消息堆积在MQ,如何解决?

惰性队列

回答

我在实际的开发中,没遇到过这种情况,不过,如果发生了堆积的问题,解决方案也所有很多的
第一:提高消费者的消费能力,可以使用多线程消费任务
第二:增加更多消费者,提高消费速度
使用工作队列模式,设置多个消费者消费消费同一个队列中的消息
第三:扩大队列容积,提高堆积上限
可以使用 RabbitMQ 惰性队列,惰性队列的好处主要是
①接收到消息后直接存入磁盘而非内存
②消费者要消费消息时才会从磁盘中读取并加载到内存
③支持数百万条的消息存储

RabbitMQ高可用机制有了解过吗?

http://www.dtcms.com/a/325342.html

相关文章:

  • RabbitMQ 消息转换器详解
  • OV5640 相机开发流程
  • 闸机控制系统从设计到实现全解析:第 5 篇:RabbitMQ 消息队列与闸机通信设计
  • C语言:贪吃蛇游戏
  • MiniCPM-V 4.0开源,号称是手机上的GPT-4V
  • 41.【.NET8 实战--孢子记账--从单体到微服务--转向微服务】--扩展功能--集成网关--网关集成Swagger
  • 量子计算:叩响金融定价革命的大门——期权定价的范式转移
  • 用Python实现Excel转PDF并去除Spire.XLS水印
  • glide缓存策略和缓存命中
  • 基于 JavaWeb+MySQL设计实现博客管理系统
  • [激光原理与应用-230]:物理学主要分支、研究对象、衍生技术及职业方向解析
  • 智慧零售的本质重构与技术创新:基于定制开发开源AI智能名片S2B2C商城小程序的实践路径
  • Redis应⽤-缓存与分布式锁
  • MySQL误删数据了,如何快速恢复?
  • GraalVM !拥抱云原生的 JVM
  • AI驱动的智能编码革命:从Copilot到全流程开发自动化
  • 2024年ESWA SCI1区TOP,自适应种群分配和变异选择差分进化算法iDE-APAMS,深度解析+性能实测
  • SysTick定时器的工作原理是什么
  • 在Linux中模拟配置高性能web服务器
  • docker compose和docker-compose命令的区别
  • 【数据可视化-86】中国育儿成本深度可视化分析(基于《中国统计年鉴2023》数据):用Python和pyecharts打造炫酷可视化大屏
  • linux常见故障 实用故障系列文章-2获取挂掉的进程pid
  • Linux kernel network stack, some good article
  • AI模型服务接入WAF防火墙
  • WebSocket-java篇
  • 有序矩阵中第K小的元素+二分查找
  • 矩阵游戏(二分图最大匹配)
  • Spring Boot 菜单删除功能的实现与事务管理
  • 数据结构——树(02构造二叉树,代码练习)
  • 《解锁 C++ 进阶密码:引用补充与内联函数、nullptr 核心用法》