Rabbit Mq 底层原理

article/2025/10/22 10:24:42

为什么要用MQ?MQ有什么好处?

1、异步通信:通过异步通信,可以减少客户端等待时间,实现接口快速响应

2、系统解耦:对于复杂的系统,减小系统与系统之间的依赖

3、流量削峰:对于瞬时访问增大,缓解服务器压力,保护服务,同时保证消息不丢失

MQ的主要特点?

1、独立运行的服务

2、使用队列数据结构进行存储数据消息(既然mq使用队列存储消息,为什么不直接使用队列进行通信,因为queue是不能跨进程的)

3、发布、订阅模型,即生产者生产消息,消费者消费消息

使用MQ带来的问题?

1、系统可用性降低了(因为mq需要部署在服务器,如果服务器出问题,系统可用性降低了)

2、系统变复杂了(需要了解mq实现原理,以及解决消息丢失、重复消费等问题)

Mq的基本特性:

1、高可靠:通过发送确认,接收确认、持久化等保证了高可靠

2、灵活的路由:通过交换机4种路由方式

3、支持多客户端:支持多语言

4、集群与扩展性:支持集群、负载均衡

5、高可用队列:镜像集群实现队列消息的复制

6、权限管理:提供给了基于用户与vhost的权限管理

7、插件系统:可视化插件

8、与spring 集成:spring Amqp实现简单

MQ工作模型?

消费者、生产者与broker进行连接采用TCP长连接方式channel虚拟信道,减少服务器资源的消耗

Rabbit Mq 4种路由方式:

binding key与rounting key

direct直连:

2、topic主题类型的交换机

#号代表:0个或者多个单词(通过英文的.来隔开单词)

*号代表:不多不少1个单词(通过英文的.来隔开单词)

3、fanout广播

4、header模式

header模式与routing不同的地方在于,header模式取消routingkey,使用header中的 key/value(键值对)匹配队列。

 

TTL过期时间:

队列的消息过期时间x-message-ttl = 10  10s钟过期

单条消息的过期时间?

如果同时设定队列消息过期时间和消息本身的过期时间,哪一个会最先失效?

队列和消息,哪个过期时间设置的小,哪个先过期。

什么是死信交换机和死信队列呢?

设置普通队列的死信交换机,死信交换机与死信队列绑定,当普通队列的消息成为死信消息就会进入死信交换机。

消息什么时候会变成死信呢?

1、消息被消费者拒绝

2、消息过期

3、队列到达了最大长度,将对头的消息丢到死信交换机上(队列到底能存储多少条消息?通过x-max-length、x-max-length-bytes参数可以设置)

 

死信队列如何使用?

 

延迟队列

延迟队列的总体方案:

1:先将消息入库,通过定时任务扫描,达到延迟时间后,将消息投递出去

2:死信队列的实现:设置消息过期时间,到达时间后消息进入死信交换机,进入死信队列,消费者消费消息

3:rabbitmq-delayed-message-exchange的实现(Liunx):实现起来简单,死信队列的延迟时间不是很精准

 

服务端流控

通过x-max-length、x-max-length-bytes这2个参数能实现服务端限流?不能,因为当这2个参数设置的值满足后,会将队头的消息移除

如果服务端产生消息的速度比消费端消费消息的速度快,那就会造成内存空间的大量占用(Mq内存节点),会占用磁盘空间(磁盘节点),如何解决?

默认如果内存低于40%的时候,mq拒绝服务端连接Conn,通过配置参数vm_memory_high_watermark控制

当占用磁盘空间低于30%时候,拒绝服务端连接,通过配置文件参数进行配置disk_free_limit.relative=3.0

当占用磁盘空间低于2G时候,拒绝服务端连接,通过配置文件参数进行配置disk_free_limit.absolute=2G

消费者消费消息会将消息缓存到本地,如果消息过多,而没有消费完,消费端限制通过设置prefetch count属性控制,如果消费端接收消息后比如5条,5条都没有给服务端应答的时候,就暂时不会进行消费消息了

 

Spring AMQP:

Spring 集成AMQP时,它做了什么?

1、帮助我们去管理对象,通过标签的方式进行配置

2、封装了rabbitMqTemplate来简化配置(rabbitTemplate)实现消息的收发

Spring AMQP包括什么?

ConnectFactory:定义虚拟机的ip、端口等等信息 连接工厂

RabbitAdmin:存放绑定关系、交换机、队列等

Message:消息对象

RabbitTemplate:消息的收发,通过定义不同的RabbitTemplate实现对不同服务器的mq进行发送消息

MessageListenerContainerFactory:动态创建队列、动态消除队列

MessageConvertor:主要是定义传输序列化格式,比如json、xml、object等等

 

Rabbit Mq可靠性投递与实践经验!!!!

1、掌握Rabbit Mq可靠性消息的投递发送

1)服务端确认机制:

1、tranction模式(不建议使用,这种方式存在阻塞,只有一条消息成功后,才会进行下一条消息)

2、confirm模式(发送一条确认一条,建议使用批量确认)

2到3过程,如何确保交换机可以把消息路由到队列呢?

路由保证:

1、mandatory = true + ReturnListener

2、指定交换机备份交换机

在当前交换机指定备份交换机去保证消息可靠性投递

交换机才有备份交换机,队列才有死信交换机

第3阶段,存储消息持久化:

1)消息持久化

2)队列持久化

3)交换机持久化

4)集群

第4步骤:

消费者确认机制ack:AutoAck

自动ack:接收到消息就发送ack

手动ack:接收到消息到处理完消息,才给服务器发送ack确认消息机制

none:自动应答

manual:手工应答

auto:自动应答,方法没发生异常才会自动应答,如果出错,则发送nack拒绝、requeue重新入队

rabbit Mq 保证消息的顺序性,一定是生产者发送到路由器和队列中的消息,消费者也需要取路由器和队列的消息,这样才能保证消息的顺序性

2、掌握Rabbit Mq集群原理与高可用架构的搭建

rabbit Mq端口:5672(单机端口)、15672(插件端口)、25672(集群端口)

erlang 语言    .erlang.cookie  进行集群通讯

集群节点的类型:disc:将交换机、队列、绑定关系、消息等放到磁盘上(主要进行数据的备份)

                             RAM:原数据放到内存中(内存节点更快速,适合应用连接)

1. 消息队列的作用与使用场景
异步:批量数据异步处理(批量上传文件)
削峰:高负载任务负载均衡(电商秒杀抢购)
解耦:串行任务并行化(退货流程解耦)
广播:基于Pub/Sub实现一对多通信

2. 多个消费者监听一个队列时,消息如何分发
轮询:默认的策略,消费者轮流,平均地接收消息
公平分发:根据消费者的能力来分发消息,给空闲的消费者发送更多消息

//当消费者有x条消息没有响应ACK时,不再给这个消费者发送消息
    channel.basicQos(int x)

3. 无法被路由的消息去了哪里
无设置的情况下,无法路由(Routing key错误)的消息会被直接丢弃
解决方案:
将mandatory设置为true,并配合ReturnListener,实现消息的回发

声明交换机时,指定备份的交换机

 Map<String,Object> arguments = new HashMap<String,Object>();
    arguments.put("alternate-exchange","备份交换机名");

4. 消息在什么时候会变成死信
消息拒绝并且没有设置重新入队
消息过期
消息堆积,并且队列达到最大长度,先入队的消息会变成DL

5. RabbitMQ如何实现延时队列
利用TTL(队列的消息存活时间或者消息存活时间),加上死信交换机

 // 设置属性,消息10秒钟过期
 AMQP.BasicProperties properties = new AMQP.BasicProperties.Builder()
                .expiration("10000") // TTL

 // 指定队列的死信交换机
 Map<String,Object> arguments = new HashMap<String,Object>();
 arguments.put("x-dead-letter-exchange","DLX_EXCHANGE");

6. 如何保证消息的可靠性投递
发送方确认模式:
将信道设置成confirm模式(发送方确认模式),则所有在信道上发布的消息都会被指派一个唯一的ID。
一旦消息被投递到目的队列后,或者消息被写入磁盘后(可持久化的消息),信道会发送一个确认给生产者(包含消息唯一ID)。
如果RabbitMQ发生内部错误从而导致消息丢失,会发送一条nack(not acknowledged,未确认)消息。
发送方确认模式是异步的,生产者应用程序在等待确认的同时,可以继续发送消息。当确认消息到达生产者应用程序,生产者应用程序的回调方法就会被触发来处理确认消息。

接收方确认机制
接收方消息确认机制:消费者接收每一条消息后都必须进行确认(消息接收和消息确认是两个不同操作)。只有消费者确认了消息,RabbitMQ才能安全地把消息从队列中删除。
这里并没有用到超时机制,RabbitMQ仅通过Consumer的连接中断来确认是否需要重新发送消息。也就是说,只要连接不中断,RabbitMQ给了Consumer足够长的时间来处理消息。保证数据的最终一致性;
下面罗列几种特殊情况:
如果消费者接收到消息,在确认之前断开了连接或取消订阅,RabbitMQ会认为消息没有被分发,然后重新分发给下一个订阅的消费者。(可能存在消息重复消费的隐患,需要去重)
如果消费者接收到消息却没有确认消息,连接也未断开,则RabbitMQ认为该消费者繁忙,将不会给该消费者分发更多的消息。

7. 消息幂等性
生产者方面:可以对每条消息生成一个msgID,以控制消息重复投递

 AMQP.BasicProperties properties = new AMQP.BasicProperties.Builder()
 porperties.messageId(String.valueOF(UUID.randomUUID()))

消费者方面:消息体中必须携带一个业务ID,如银行流水号,消费者可以根据业务ID去重,避免重复消费

8. 消息如何被优先消费

//生产者
 Map<String, Object> argss = new HashMap<String, Object>();
        argss.put("x-max-priority",10);

//消费者
AMQP.BasicProperties properties = new AMQP.BasicProperties.Builder()
                .priority(5) // 优先级,默认为5,配合队列的 x-max-priority 属性使用

9. 如何保证消息的顺序性
一个队列只有一个消费者的情况下才能保证顺序,否则只能通过全局ID实现(每条消息都一个msgId,关联的消息拥有一个parentMsgId。可以在消费端实现前一条消息未消费,不处理下一条消息;也可以在生产端实现前一条消息未处理完毕,不发布下一条消息)

10. RabbitMQ的集群模式和集群节点类型

mq集群节点分为内存节点和磁盘节点


**普通模式:**默认模式,以两个节点(rabbit01,rabbit02)为例来进行说明,对于Queue来说,消息实体只存在于其中一个节点rabbit01(或者rabbit02),rabbit01和rabbit02两个节点仅有相同的元数据,即队列结构。当消息进入rabbit01节点的Queue后,consumer从rabbit02节点消费时,RabbitMQ会临时在rabbit01,rabbit02间进行消息传输,把A中的消息实体取出并经过B发送给consumer,所以consumer应尽量连接每一个节点,从中取消息。即对于同一个逻辑队列,要在多个节点建立物理Queue。否则无论consumer连rabbit01或rabbit02,出口总在rabbit01,会产生瓶颈。当rabbit01节点故障后,rabbit02节点无法取到rabbit01节点中还未消费的消息实体。如果做了消息持久化,那么等到rabbit01节点恢复,然后才可被消费。如果没有消息持久化,就会产生消息丢失的现象。

**镜像模式:**把需要的队列做成镜像队列,存在与多个节点属于RabibitMQ的HA方案,该模式解决了普通模式中的问题,其实质和普通模式不同之处在于,消息体会主动在镜像节点间同步,而不是在客户端取数据时临时拉取,该模式带来的副作用也很明显,除了降低系统性能外,如果镜像队列数量过多,加之大量的消息进入,集群内部的网络带宽将会被这种同步通讯大大消耗掉,所以在对可靠性要求比较高的场合中适用

节点分为内存节点(保存状态到内存,但持久化的队列和消息还是会保存到磁盘),磁盘节点(保存状态到内存和磁盘),一个集群中至少需要一个磁盘节点

11.如何自动删除长时间没有消费的消息

// 通过队列属性设置消息过期时间
        Map<String, Object> argss = new HashMap<String, Object>();
        argss.put("x-message-ttl",6000);

 // 对每条消息设置过期时间
        AMQP.BasicProperties properties = new AMQP.BasicProperties.Builder()
                .expiration("10000") // TTL

12.消息基于什么传输
AMQP协议,RabbitMQ使用信道的方式来传输数据。信道是建立在真实的TCP连接内的虚拟连接,且每条TCP连接上的信道数量没有限制

13.如何确保消息不丢失
消息持久化,当然前提是队列必须持久化
RabbitMQ确保持久性消息能从服务器重启中恢复的方式是,将它们写入磁盘上的一个持久化日志文件,当发布一条持久性消息到持久交换器上时,Rabbit会在消息提交到日志文件后才发送响应。
一旦消费者从持久队列中消费了一条持久化消息,RabbitMQ会在持久化日志中把这条消息标记为等待垃圾收集。如果持久化消息在被消费之前RabbitMQ重启,那么Rabbit会自动重建交换器和队列(以及绑定),并重新发布持久化日志文件中的消息到合适的队列。

 

 

 

 

channel和vhost的作用是什么?

channal是减少连接数

vhost节省硬件资源

交换机与队列、队列与消费者的绑定关系?

多对多

队列与消费者为1对多的时候,会采用轮训机制调用消费者,每次拿几条是prefetch count来决定的

无法被路由的消息,去哪里了?

直接被丢弃   解决是备份交换机、回发

消息在什么情况下会进入死信?

消息过期、消息被拒绝、消息超过了队列的长度

 

rabbit Mq如何实现延迟队列?

1、将消息放入数据库,通过定时任务去扫描,发送消息

2、通过TTl加死信队列来实现延迟队列

3、通过delay-message插件

哪些情况会导致消息丢失?如何解决?

一个队列最多可以存放多少条消息?取决于硬件配置,如果参数做了持久化,无论是内存节点还是磁盘节点都会放到磁盘上

如何提高消息的消费速率呢?

增加消费者

如何动态的创建队列和消费者?listenerContainer

大量消息堆积如何处理?增加消费者、直接把队列清空掉、重启服务

设计一个mq?

存储、转发


http://chatgpt.dhexx.cn/article/yoppxPJ6.shtml

相关文章

RabbitMQ工作原理以及常见面试题【2022版】

RabbitMQ工作原理图&#xff1a; Broker&#xff1a;接收和分发消息的应用&#xff0c;RabbitMQ Server 就是 Message Broker Virtual host&#xff1a;出于多租户和安全因素设计的&#xff0c;把 AMQP 的基本组件划分到一个虚拟的分组中&#xff0c;类似 于网络中的 namespac…

RabbitMQ原理简单介绍

其实这篇博客&#xff0c;也算不上是什么原理&#xff0c;只是将我知道的一些RabbitMQ的知识简单罗列下&#xff0c;自从我来公司到现在&#xff0c;虽然一直都在用RabbitMQ&#xff0c;也一直想着把这块总结下&#xff0c;却一直在给自己找借口&#xff0c;最近一段时间&#…

MQ - RabbitMQ - 架构及工作原理

参考网址&#xff1a; RabbitMQ的应用场景以及基本原理介绍 RabbitMQ使用详解 RabbitMQ的Java应用(1) -- Rabbit Java Client使用 1. 系统架构 几个概念说明: Broker:它提供一种传输服务,它的角色就是维护一条从生产者到消费者的路线&#xff0c;保证数据能按照指定的方式进…

RabbitMQ 详解

RabbitMQ 详解 MQ 的相关概念RabbitMQ 四大核心概念RabbitMQ 的工作原理RabbitMQ 六大核心部分&#xff08;模式&#xff09;简单模式工作模式工作模式案例消息确认&#xff08;消息应答&#xff09;消息持久化 发布确认模式交换机&#xff08;Exchange&#xff09;Exchange 概…

RabbitMq原理及应用

一、简介 MQ(Message Queue),即消息队列&#xff0c;是一种实现应用级别之间的通信手段。不同应用之间可以通过读写消息&#xff0c;以消息为媒介传递应用数据&#xff0c;不需要应用之间建立强连接。此方式与远程调用&#xff08;RPC&#xff09;是应用通信的常见方式。在这个…

RabbitMQ原理解析

场景模拟 在介绍RabbitMQ之前&#xff0c;我们先来看下面一个电商项目的场景&#xff1a; 商品的原始数据保存在数据库中&#xff0c;增删改查都在数据库中完成。搜索服务数据来源是索引库&#xff08;Elasticsearch&#xff09;&#xff0c;如果数据库商品发生变化&#xff0…

Rabbitmq基本原理和架构

全栈工程师开发手册 &#xff08;作者&#xff1a;栾鹏&#xff09; 架构系列文章 rabbitmq官网:https://www.rabbitmq.com/rabbitmqctl.8.html MQ全称为Message Queue, 是一种分布式应用程序的的通信方法&#xff0c;它是消费-生产者模型的一个典型的代表&#xff0c;produc…

RabbitMQ — RabbitMQ使用以及原理解析

RabbitMQ使用以及原理解析 RabbitMQ是一个由erlang开发的AMQP(Advanved Message Queue)的开源实现;在RabbitMQ官网上主要有这样的模块信息, Work queues消息队列,Publish/Subscribe发布订阅服务,Routing, Topics, RPC等主要应用的模块功能. 几个概念说明: Broker:它提供一种传…

RabbitMQ介绍及工作原理

RabbitMQ介绍及工作原理 一&#xff0c;什么是RabbitMQ ​ RabbitMQ是一种称为消息代理或队列管理器的消息队列软件。它是一个可以定义队列的软件&#xff0c;应用程序可以连接到队列并将消息传输到它们。消息队列的基本体系结构很简单&#xff1a;存在称为生产者的客户端应用…

彻底理解RabbitMQ底层原理

1.RabbitMQ概念 RabbitMQ 是一个由 Erlang 语言开发的 AMQP 的开源实现。 AMQP &#xff1a;Advanced Message Queue&#xff0c;高级消息队列协议。它是应用层协议的一个开放标准 &#xff0c;为 面向消息的中间件设计&#xff0c;基于此协议的客户端与消息中间件可传递消息&…

rabbitmq消息队列原理

一、rabbitmq架构 RabbitMQ是一个流行的开源消息队列系统&#xff0c;是AMQP&#xff08;高级消息队列协议&#xff09;标准的实现&#xff0c;由以高性能、健壮、可伸缩性出名的Erlang语言开发&#xff0c;并继承了这些优点。rabbitmq简单架构如下&#xff1a; 上图简单展…

SpringBoot整合RabbitMQ及其原理分析

上一篇&#xff1a;RabbitMQ基础知识 1、相关依赖 这里无需指定版本号&#xff0c;让其跟着SpringBoot版本走。本示例使用SpringBoot版本号为2.7.10。 <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-…

rabbitmq详解

rabbitmq 一、简介二、业务场景1、异步2、应用解耦3、流量削峰 三、下载四、界面认识五、五种模型示例0、springboot依赖配置1、Hello World简单模型2、Work queues工作队列3、Publish/Subscribe发布订阅模型4、Routing路由模型5、Topics主题模型6、消息转换器 六、进阶1、消费…

[RabbitMQ--1] MQ简介

目录 1.MQ 的相关概念 1.1.什么是 MQ&#xff1f; 1.2.为什么要用MQ&#xff1f;MQ的应用场景 1.2.1.流量消峰&#xff1a; 1.2.2.任务异步处理&#xff1a; 1.2.3.应用解耦 2.AMQP和JMS 3.MQ 的分类 1.ActiveMQ 2.Kafka 3..RocketMQ 4..RabbitMQ 4.RabbitMQ 1.四…

什么是RabbitMq?其原理?

什么是RabbitMq&#xff1f; RabbitMQ是一个实现了AMQP&#xff08;Advanced Message Queuing Protocol&#xff09;高级消息队列协议的消息队列服务&#xff0c;用Erlang语言。 rabbitmq原理 1.Producer&#xff1a;即数据的发送方。创建消息并将其发布(发送)到代理服务器 一…

RabbitMQ原理详解

RabbitMQ&#xff1a;我们通常谈到消息队列&#xff0c;就会联想到这其中的三者&#xff1a;生产者、消费者和消息队列&#xff0c;生产者将消息发送到消息队列&#xff0c;消费者从消息队列中获取消息进行处理。对于RabbitMQ&#xff0c;它在此基础上做了一层抽象&#xff0c;…

你应该知道的 9 种 前端设计模式

本篇文章给大家介绍 9 种 前端设计模式。有一定的参考价值&#xff0c;有需要的朋友可以参考一下&#xff0c;希望对大家有所帮助。 什么是设计模式&#xff1f; 设计模式是对软件设计开发过程中反复出现的某类问题的通用解决方案。设计模式更多的是指导思想和方法论&#xff…

前端需要了解的设计模式

什么是设计模式&#xff1f; 设计模式是对软件设计开发过程中反复出现的某类问题的通用解决方案。设计模式更多的是指导思想和方法论&#xff0c;而不是现成的代码&#xff0c;当然每种设计模式都有每种语言中的具体实现方式。学习设计模式更多的是理解各种模式的内在思想和解…

前端设计模式应用

前端设计模式应用 什么是设计模式 软件设计中常见问题的解决方案模型: 历史经验的总结与特定语言无关 设计模式背景 模式语言:城镇、建筑、建造 (A Pattern Language:Towns, Buildings,Construction)1977设计模式:可复用面向对象软件的基础 (Design Patterns: Elements of …

web端设计和web前端开发的区别

Web前端开发技术主要包括三个要素&#xff1a;HTML、CSS和JavaScript&#xff01; 它要求前端开发工程师不仅要掌握基本的Web前端开发技术&#xff0c;网站性能优化、SEO和服务器端的基础知识&#xff0c;而且要学会运用各种工具进行辅助开发以及理论层面的知识&#xff0c;包括…