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

《深入浅出RabbitMQ:从零基础到面试通关》

  • 博客主页:天天困啊
  • 系列专栏:面试题
  • 关注博主,后期持续更新系列文章
  • 如果有错误感谢请大家批评指出,及时修改
  • 感谢大家点赞👍收藏⭐评论✍

什么是消息队列?

基本定义

  1. 消息队列(Message Queue)是一种进程间通信或同一进程内不同线程间通信的机制
  2. 他采用先进先出(FIFO)的数据结构来存储和传递消息
  3. 是分布式系统中重要的异步通信组件

核心组成要素

  1. 消息(Message):需要传递的数据单元
  2. 队列(Queue):存储消息的容器
  3. 生产者(Producer):发送消息的应用程序
  4. 消费者(Consumer):接受并处理消息的应用程序

为什么要学习消息队列?

1.解决系统耦合问题

  • 降低系统间直接依赖,提供系统耦合性
  • 支持异步处理,提升系统响应速度

2.提高系统性能和可拓展性

  • 实现削峰填谷,应对流量波动
  • 支持水平扩展,提高系统吞吐量

3.保证数据可靠性

  • 提供持久化机制,防止数据丢失
  • 支持事务性消息,确保数据一致性

4.应用场景广泛

  • 订单处理、日志收集、邮件发送等业务场景
  • 微服务架构中的服务间通信

5.技术面试必备

  • 是互联网公司后端开发岗位的高频面试题
  • 体现对分布式系统设计的理解能力

为什么要使用消息队列?(面试题)

从以前的单体架构到现在的微服务架构,服务器之间要互相依赖调用,我们需要一个技术来解耦之前的服务和流量控制,还可以异步来处理一些任务提供系统的性能

所以消息队列的主要目的就是:解耦服务异步处理削峰填谷(流量控制)

消息队列还具有可靠性高可拓展性等优点

常见的消息队列哪些?(面试题)

ActiveMQ、RabbitMQ、RocketMQ、Kafka

他们之间的区别有哪些?(面试题)

消息队列可用性吞吐量可靠性时效性应用场景
ActiveMQ中等千~万级中等毫秒级适用于对时效性要求较高但吞吐量不大的传统企业应用 适合需要多种协议支持(如JMS、AMQP、STOMP等)的场景
RabbitMQ万~十万级毫秒级适用于对消息可靠性、实时性要求高的场景 常用于金融、电商订单处理、即时通讯等业务系统
RocketMQ十万级毫秒~秒级适用于对可靠性要求高、有一定吞吐量需求的互联网应用
常用于订单处理、交易系统、日志收集等场景
Kafka百万级中等秒级适用于大数据处理、日志收集、流式计算等高吞吐量场景
常用于实时数据管道、事件溯源、监控数据处理

在国内互联网企业中,RabbitMQ是比较主流的选择,我们此次就讲解RabbitMQ

RabbitMQ中架构是什么样子?核心组件有哪些?(面试题)

  1. Producer(生产者):生产消息,是发消息的一方,将消息发送到交换机
  2. Consumer(消费者):消费消息,是消费消息的一方,属于消息的接收方,接收并处理队列中的消息
  3. Queue(队列):存储消息,生产者的消息会暂时存在队列中,等待消费者从队列中获取消息并处理
  4. Exchange(交换机):交换机是消息的接收和路由转发,它接收来自消费者的消息,根据绑定键将消息分配到一个队列或者多个队列中
  5. Binding(绑定):绑定是交换机和队列之间关联的关系,定义了交换机将消息转发到哪个队列上的规则
  6. VirtualHost(虚拟主机):起到数据隔离的作用。每个虚拟机主机都是相互独立的个体,有各自的交换机、队列和绑定关系等。不同之间的虚拟机主机互不干扰
  7. Routing Key(路由键):交换机到队列的路由规则
  8. Connection(连接):客户端与服务器之间的网络连接
  9. Channel(信道):连接作用,进行消息的读写操作

RabbitMQ中如何实现延迟消息(面试题)?

有两种方式可以实现延迟消息,第一种是通过死信交换机,第二种是通过插件的方式

方案一实现步骤:

  1. 创建普通业务交换机和队列:定义用于接收原始消息的交换机和队列
  2. 配置队列的死信交换机:通过队列参数指定死信消息的目标交换机,可选配置指定死信消息的路由键
  3. 设置消息过期时间:为整个队列设置统一过期时间,或者在发送消息的时候为单个消息设置独立过期时间
  4. 创建死信交换机和队列:定义一个死信交换机和死信队列
  5. 绑定死信路由:讲死信交换机与死信队列进行绑定
  6. 消费延迟消息:消费者监听死信队列,处理到期的延迟消息

方案二实现步骤:

  1. 安装并启用插件:下载并安装插件
  2. 创建延迟交换机:声明类型为x-delayed-message的交换机
  3. 发送延迟消息:在发送消息时,通过消息头部的x-deplay属性设置延迟时间(毫秒)
  4. 正常消费消息:插件会在指定延迟时间后将消息投递到目标队列

扩展知识

死信队列是RabbitMQ中用于存储“死信”消息的特殊队列。当正常队列中的消息由于某些原因无法被正常消费时,这些消息就会被变成“死信”,并被自动转发到预先配置的死信队列中。死信是指消息被拒绝,消息在队列中存活时间超过设置的TTL,队列消息数量达到上限,新消息导致旧消息被移除

什么是RabbitMQ的死信队列(面试题)?

死信队列(Dead Letter Queue,简称DLQ) 是一种用于处理无法正常消费的消息的机制。当消息在常规队列中由于各种原因无法被成功消费时,这些消息会被自动转移到死信队列中。这样可以避免消息丢失,并为后续的分析、排查或重试提供机会

消息可能因为以下几种情况而成为死信

  1. 消息处理失败:消费者在处理消息时遇到错误(如代码错误、消息格式不正确、业务规则冲突等),导致消息无法被成功处理
  2. 消息过期:RabbitMQ支持为消息设置TTL(Time To Live)。如果消息在指定的时间内未被消费,它将被视为死信并被移至死信队列
  3. 消息被拒绝:消费者显式拒绝一条消息(使用 basic.reject 或 basic.nack 且 requeue=false),该消息会被标记为死信并发送到死信队列
  4. 消息无法路由:如果消息无法被路由到任何队列(例如,没有匹配的绑定关系或路由键),则该消息也会被发送到死信队列

死信队列的优势

  1. 提高系统可靠性:防止重要消息因处理失败而丢失
  2. 便于问题排查:集中管理异常消息,方便后续分析和处理
  3. 实现延迟重试:结合TTL功能,实现消息的延迟重试机制

配置死信队列

  1. 在RabbitMQ中配置死信队列需要以下几个步骤:
  2. 创建死信交换机(DLX)和死信队列(DLQ)
  3. 配置普通队列,指定其死信交换机

配置示例代码

import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;
import java.util.HashMap;
import java.util.Map;public class DeadLetterQueueConfig {private static final String NORMAL_EXCHANGE = "normal_exchange";private static final String DLX_EXCHANGE = "dlx_exchange";private static final String NORMAL_QUEUE = "normal_queue";private static final String DLX_QUEUE = "dlx_queue";public static void main(String[] args) throws Exception {// 1. 创建连接ConnectionFactory factory = new ConnectionFactory();factory.setHost("localhost");try (Connection connection = factory.newConnection();Channel channel = connection.createChannel()) {// 2. 创建死信交换机和死信队列channel.exchangeDeclare(DLX_EXCHANGE, "direct");channel.queueDeclare(DLX_QUEUE, true, false, false, null);channel.queueBind(DLX_QUEUE, DLX_EXCHANGE, "dlx_routing_key");// 3. 创建普通交换机和队列,并配置死信交换机channel.exchangeDeclare(NORMAL_EXCHANGE, "direct");Map<String, Object> arguments = new HashMap<>();arguments.put("x-dead-letter-exchange", DLX_EXCHANGE); // 设置死信交换机arguments.put("x-dead-letter-routing-key", "dlx_routing_key"); // 设置死信路由键arguments.put("x-message-ttl", 10000); // 可选:设置消息TTL(10秒)channel.queueDeclare(NORMAL_QUEUE, true, false, false, arguments);channel.queueBind(NORMAL_QUEUE, NORMAL_EXCHANGE, "normal_routing_key");System.out.println("死信队列配置完成!");}}
}

扩展知识

1. DLX配置细节

  • x-dead-letter-exchange:指定死信交换机名称。
  • x-dead-letter-routing-key:指定死信消息的路由键。
  • x-message-ttl:可选参数,设置消息的生存时间(单位:毫秒)

2. 死信情况具体解释

  • 消息被拒绝(rejected):通过 basic.reject 或 basic.nack 方法且 requeue=false 时,消息会被发送到死信队列
  • 消息过期(TTL到期):如果消息设置了TTL且在规定时间内未被消费,将被视为死信
  • 队列长度限制:当队列的消息数量达到最大限制时,最早的消息会被移除并标记为死信

RabbiMQ中如何防止重复消费(面试题)?

 确保消息处理的幂等性

1.幂等性 指的是多次执行同一操作的结果与一次执行的结果相同。在消息队列中,这意味着即使消息被多次消费,其最终结果也是一致的

  • 自动确认模式:消息一旦被消费者接收即被视为已处理,这种方式简单但不推荐,因为它无法处理消息处理失败的情况
  • 手动确认模式:消费者在成功处理消息后手动发送 ack,如果消费者在处理消息过程中发生异常或崩溃,RabbitMQ 会将消息重新投递给其他消费者

2.消息确认机制(Acknowledgment)

RabbitMQ 提供了消息确认机制,消费者在成功处理消息后需要显式地向 RabbitMQ 发送确认(ack)

  • 自动确认模式:消息一旦被消费者接收即被视为已处理,这种方式简单但不推荐,因为它无法处理消息处理失败的情况
  • 手动确认模式:消费者在成功处理消息后手动发送 ack,如果消费者在处理消息过程中发生异常或崩溃,RabbitMQ 会将消息重新投递给其他消费者

3. 消息持久化与状态记录

将已处理的消息状态持久化存储,可以有效避免重复消费

  • 数据库记录:每次成功处理一条消息后,将其 messageId 或其他唯一标识存储到数据库中。下次接收到相同的消息时,先查询数据库判断是否已处理
  • Redis 缓存:利用 Redis 的高性能特性,将已处理的消息 messageId 存储在 Redis 中,设置合理的过期时间以节省内存

4. 使用唯一消息 ID

为每条消息分配一个唯一的 messageId,并在消息处理前进行校验

  • 生成唯一 ID:在消息生产阶段为每条消息生成一个全局唯一的 messageId
  • 校验 messageId:消费者在处理消息前,首先检查该 messageId 是否已存在于存储系统(如数据库或 Redis)中,如果存在则跳过处理

以上就是RabbitMQ相关的高频面试题及详细解答,涵盖了从基础概念到高级特性的各个方面。在准备面试时,不仅要理解这些知识点,更重要的是要结合实际业务场景进行思考。建议读者在学习过程中多动手实践,通过搭建测试环境来验证各种特性和配置的效果,这样才能在面试和工作中游刃有余

http://www.xdnf.cn/news/1235863.html

相关文章:

  • 渗透作业4
  • wordpress登陆前登陆后显示不同的顶部菜单
  • 数据结构代码
  • 08.Redis 持久化
  • AOP动态代理
  • #C语言——刷题攻略:牛客编程入门训练(四):运算
  • 大屏项目展示
  • 面向智能体的上下文工程:策略、实现与 LangGraph 实践
  • 09.Redis 常用命令
  • STM32-ESP8266通过MQTT与阿里云通讯
  • Coze 打通飞书多维表格,实现数据增删改查操作实战详解
  • Java线程安全类设计思路总结
  • kafka 是一个怎样的系统?是消息队列(MQ)还是一个分布式流处理平台?
  • RabbitMQ死信队列与消息幂等性实践指南
  • Rust:如何访问 *.ini 配置文件?
  • 关于车位引导及汽车乘梯解决方案的专业性、系统性、可落地性强的综合设计方案与技术实现说明,旨在为现代智慧停车楼提供高效、安全、智能的停车体验。
  • Noob靶场练习
  • 【python实用小脚本-169】『Python』所见即所得 Markdown 编辑器:写完即出网页预览——告别“写完→保存→刷新”三连
  • Rustdesk中继服务器搭建(windows 服务器)
  • SQL注入SQLi-LABS 靶场less31-38详细通关攻略
  • Python篇--- Python 的加载、缓存、覆盖机制
  • (FD Conv)Frequency Dynamic Convolution for Dense Image Prediction论文精读(逐段解析)
  • vscode的Remote-SSH插件配置SSH主机方法
  • 构造类型--结构体,共同体联合体,枚举
  • 知识蒸馏 - 基于KL散度的知识蒸馏 HelloWorld 示例 采用PyTorch 内置函数F.kl_div的实现方式
  • 标记-清除算法中的可达性判定与Chrome DevTools内存分析实践
  • Rust: 获取 MAC 地址方法大全
  • webrtv弱网-QualityScalerResource 源码分析及算法原理
  • 集成电路学习:什么是USB HID人机接口设备
  • Hertzbeat如何配置redis?保存在redis的数据是可读数据