一文掌握RabbitMQ核心概念和原理

  本文主要通过图文的方式介绍了RabbitMQ核心概念和原理,包括工作模型、交换机类型、交换机和队列的详细属性、过期消息、死信队列、延迟队列、消息可靠性和幂等性、集群分类等方面。

文章目录

  • 消息中间件
    • 概念
    • 应用场景
  • RabbitMQ工作模型和基本概念
  • RabbitMQ交换机类型
  • 交换机详细属性
  • 队列详细属性
  • 过期消息
  • 死信队列
  • 延迟队列
  • 消息可靠性
    • 消息Confirm确认模式
    • 消息Return返回模式
  • 消息的幂等性
  • 集群与高可用
    • 默认集群模式
    • 镜像集群模式

消息中间件

概念

  消息中间件就是指保存数据的一个容器(服务器),可以用于两个系统之间的数据传递。消息中间件一般有三个主要角色:生产者、消费者、消息代理(消息队列、消息服务器);生产者发送消息到消息服务器,然后消费者从消息代理(消息队列)中获取数据并进行处理;

在这里插入图片描述

应用场景

1.异步处理
一个主流程含有多个子流程的情况下,各个子流程可以借用消息中间件实现异步处理,从而加快处理速率。例如业务有5个子流程,但其余4个子流程无需返回给用户的情况:
在这里插入图片描述

2.系统解耦
多个系统之间,不需要直接交互,通过消息进行业务流转
在这里插入图片描述

3.流量削峰
高负载请求/任务的缓冲处理
在这里插入图片描述

4.日志处理
解决大量日志传输问题,一般使用kafka


RabbitMQ工作模型和基本概念

在这里插入图片描述

对于以上模型的关键要素解释,可用同比mysql为例进行解释:
  broker 相当于mysql服务器
  virtual host 相当于数据库(可以有多个数据库)
  queue 相当于表
  queue 中的消息相当于表中的记录。

核心概念汇总

概念说明
生产者 Producer发送消息的应用;(java程序,也可能是别的语言写的程序)
消费者 Consumer接收消息的应用;(java程序,也可能是别的语言写的程序)
代理 Broker就是消息服务器,RabbitMQ Server就是Message Broker
连接 Connection连接RabbitMQ服务器的TCP长连接
信道 Channel连接中的一个虚拟通道,消息队列发送或者接收消息时,都是通过信道进行的
虚拟主机 Virtual host一个虚拟分组,可以划分出多个Virtual host,每个Virtual host创建exchange/queue等(分类比较清晰、相互隔离)
交换机 Exchange交换机负责从生产者接收消息,并根据交换机类型分发到对应的消息队列中,起到一个路由的作用
路由键 Routing Key交换机根据路由键来决定消息分发到哪个队列,路由键是消息的目的地址
绑定 Binding绑定是队列和交换机的一个关联连接(关联关系)
队列 Queue存储消息的缓存
消息 Message由生产者通过RabbitMQ发送给消费者的信息;(消息可以任何数据,字符串、user对象,json串等等)

RabbitMQ交换机类型

1.Fanout Exchange(扇形)
投递到所有绑定的队列,不需要路由键,不需要进行路由键的匹配,相当于广播、群发
在这里插入图片描述

2.Direct Exchange(直连)
根据路由键精确匹配(一模一样)进行路由消息队列
在这里插入图片描述

3.Topic Exchange(主题)
通配符匹配,相当于模糊匹配;
#号,匹配多个单词,用来表示任意数量(零个或多个)单词
*号,匹配一个单词(必须有一个,而且只有一个),用.隔开的为一个单词:
示例:

beijing.# == beijing.queue.abc, beijing.queue.xyz.xxx
beijing.* == beijing.queue, beijing.xyz

在这里插入图片描述

4.Headers Exchange(头部)
基于消息内容中的headers属性进行匹配;
在这里插入图片描述
示例:

MessageProperties messageProperties = new MessageProperties();
messageProperties.setHeader("type", "m");
messageProperties.setHeader("status", 1);

经过以上配置后,消息发送时会路由到对应队列中,例如图中的Q9队列

交换机详细属性

属性解释
Name交换机名称;就是一个字符串
Type交换机类型,direct, topic, fanout, headers四种
Durability持久化,声明交换机是否持久化,代表交换机在服务器重启后是否还存在
Auto delete是否自动删除,曾经有队列绑定到该交换机,后来解绑了,那就会自动删除该交换机
Internal内部使用的,如果是yes,客户端无法直接发消息到此交换机,它只能用于交换机与交换机的绑定
Arguments只有一个取值alternate-exchange,表示备用交换机

备用交换机
  当消息经过交换器准备路由给队列的时候,发现没有对应的队列可以投递信息,在rabbitmq中会默认丢弃消息,如果我们想要监测哪些消息被投递到没有对应的队列,我们可以用备用交换机来实现,可以接收备用交换机的消息,然后记录日志或发送报警信息。概念示意图如下,x表示正常交换机
在这里插入图片描述

队列详细属性

属性解释
Name交换机名称;就是一个字符串
Type交换机类型,direct, topic, fanout, headers四种
Durability持久化,声明交换机是否持久化,代表交换机在服务器重启后是否还存在
Auto delete是否自动删除,曾经有队列绑定到该交换机,后来解绑了,那就会自动删除该交换机
Internal内部使用的,如果是yes,客户端无法直接发消息到此交换机,它只能用于交换机与交换机的绑定
Arguments只有一个取值alternate-exchange,表示备用交换机

Arguments 详细参数

参数含义
x-expires当Queue(队列)在指定的时间未被访问,则队列将被自动删除
x-message-ttl发布的消息在队列中存在多长时间后被取消(单位毫秒)
x-overflow设置队列溢出行为,当达到队列的最大长度时,消息会发生什么,有效值为Drop Head或Reject Publish
x-max-length队列所能容下消息的最大长度,当超出长度后,新消息将会覆盖最前面的消息,类似于Redis的LRU算法
x-single-active-consumer激活单一的消费者,也就是该队列只能有一个消息者消费消息,默认为false
x-max-length-bytes限定队列的最大占用空间,当超出后也使用类似于Redis的LRU算法
x-dead-letter-exchange指定队列关联的死信交换机,有时候我们希望当队列的消息达到上限后溢出的消息不会被删除掉,而是走到另一个队列中保存起来
x-dead-letter-routing-key指定死信交换机的路由键,一般和6一起定义
.x-max-priority如果将一个队列加上优先级参数,那么该队列为优先级队列

过期消息

过期消息也叫TTL消息,TTL:Time To Live。有以下两种方式来设置过期消息

1.设置单条消息的过期时间

MessageProperties messageProperties = new MessageProperties();
messageProperties.setExpiration("15000"); // 设置过期时间,单位:毫秒

2.通过队列属性设置消息过期时间:

@Bean
public Queue directQueue() {
    Map<String, Object> arguments = new HashMap<>();
    arguments.put("x-message-ttl", 10000);
    return new Queue(DIRECT_QUEUE, true, false, false, arguments);
}

死信队列

DLX: Dead-Letter-Exchange 死信交换器
在这里插入图片描述
如下情况下一个消息会进入DLX(Dead Letter Exchange)死信交换机
1.消息过期
2.队列过期
3.队列达到最大长度(先入队的消息会被发送到DLX)
4.消费者对消息不进行确认,并且不对消息进行重新投递
5.消费者拒绝消息

延迟队列

  RabbitMQ本身不支持延迟队列,可以使用TTL结合DLX的方式来实现消息的延迟投递,即把DLX跟某个队列绑定,到了指定时间,消息过期后,就会从DLX路由到这个队列,消费者可以从这个队列取走消息。
在这里插入图片描述
问题: 如果先发送的消息,消息延迟时间长,会影响后面的延迟时间段的消息的消费;
解决:不同延迟时间的消息要发到不同的队列上,同一个队列的消息,它的延迟时间应该一样

在这里插入图片描述

rabbitmq提供插件,可以实现延迟队列功能。
rabbitmq-delayed-message-exchange 延迟插件原理:
消息发送后不会直接投递到队列,而是存储到 Mnesia(嵌入式数据库)

在这里插入图片描述

消息可靠性

在这里插入图片描述
可通过以下方式保证上图每个环节的可靠性
1.确保消息发送到RabbitMQ服务器的交换机上
Confirm(确认)模式

2.确保消息路由到正确的队列
return模式,可以实现消息无法路由的时候返回给生产者;
另一种方式就是使用备份交换机

3.确保消息在队列正确地存储
队列、交换机、消息持久化

4.消费者监听Queue并消费消息
采用消息消费时的手动ack确认机制来保证,配置开启手动消息消费确认
spring.rabbitmq.listener.simple.acknowledge-mode=manual

消息Confirm确认模式

  消息的confirm确认机制,是指生产者投递消息后,到达了消息服务器Broker里面的exchange交换机,则会给生产者一个应答,生产者接收到应答,用来确定这条消息是否正常的发送到Broker的exchange中,这也是消息可靠性投递的重要保障;
在这里插入图片描述
配置文件application.yml 开启确认模式:设置关联模式

spring.rabbitmq.publisher-confirm-type=correlated

代码:写一个类实现implements RabbitTemplate.ConfirmCallback

消息Return返回模式

rabbitmq 整个消息投递的路径为:
producer —> exchange —> queue —> consumer

【Confirm确认模式】消息从 producer –> exchange 则会返回一个 confirmCallback;
【Return返回模式】消息从 exchange –> queue 投递失败则会返回一个 returnCallback;

配置中开启return模式

spring.rabbitmq.publisher-returns: true

代码:写一个类实现implements RabbitTemplate.ReturnsCallback

消息的幂等性

  消息消费时的幂等性是指消息不被重复消费。同一个消息,第一次接收,正常处理业务,如果该消息第二次再接收,那就不能再处理业务,否则就处理重复了;一般来说,增删改都是非幂等的。

如何避免消息的重复消费问题:全局唯一ID + Redis
  生产者在发送消息时,为每条消息设置一个全局唯一的messageId,消费者拿到消息后,使用setnx命令,将messageId作为key放到redis中:setnx(messageId, 1),若返回1,说明之前没有消费过,正常消费;若返回0,说明这条消息之前已消费过,抛弃;

集群与高可用

  分布式系统一定是集群的,首先解决单点故障问题(SPOF)。RabbitMQ 的集群分两种模式,一种是默认集群模式,一种是镜像集群模式;
  在RabbitMQ集群中所有的节点(一个节点就是一个RabbitMQ的broker服务器) 被归为两类:一类是磁盘节点【至少要有1个】,一类是内存节点;至少要有一个磁盘节点是为了避免关机后数据消失。

默认集群模式

  RabbitMQ默认集群模式,只会把交换机、队列、虚拟主机等元数据信息在各个节点同步,而具体队列中的消息内容不会在各个节点中同步;

元数据:数据的数据。队列名称和属性;交换器名称、类型和属性

  消息消费者所连接的节点2或者节点3,那这两个节点也会作为路由节点起到转发作用,将会从节点1的队列1中获取消息进行消费【生产也是类似】

在这里插入图片描述

镜像集群模式

  把所有的队列数据完全同步,包括元数据信息和消息数据信息


参考来源
动力节点RabbitMQ教程

觉得文章有帮助可以点个赞或关注支持一下哟~

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/529892.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

GitHub 仓库 (repository) Pulse - Contributors - Network

GitHub 仓库 [repository] Pulse - Contributors - Network 1. Pulse2. Contributors3. NetworkReferences 1. Pulse 显示该仓库最近的活动信息。该仓库中的软件是无人问津&#xff0c;还是在火热地开发之中&#xff0c;从这里可以一目了然。 2. Contributors 显示对该仓库进…

【数据结构】考研真题攻克与重点知识点剖析 - 第 7 篇:查找

前言 本文基础知识部分来自于b站&#xff1a;分享笔记的好人儿的思维导图与王道考研课程&#xff0c;感谢大佬的开源精神&#xff0c;习题来自老师划的重点以及考研真题。此前我尝试了完全使用Python或是结合大语言模型对考研真题进行数据清洗与可视化分析&#xff0c;本人技术…

微信小程序Skyline模式下瀑布长列表优化成虚拟列表,解决内存问题

微信小程序长列表&#xff0c;渲染的越多就会导致内存吃的越多。特别是长列表的图片组件和广告组件。 为了解决内存问题&#xff0c;所以看了很多人的资料&#xff0c;都不太符合通用的解决方式&#xff0c;很多需要固定子组件高度&#xff0c;但是瀑布流是无法固定的&#xf…

STM32H7通用定时器计数功能的使用

目录 概述 1 STM32定时器介绍 1.1 认识通用定时器 1.2 通用定时器的特征 1.3 递增计数模式 1.4 时钟选择 2 STM32Cube配置定时器时钟 2.1 配置定时器参数 2.2 配置定时器时钟 3 STM32H7定时器使用 3.1 认识定时器的数据结构 3.2 计数功能实现 4 测试案例 4.1 代码…

三极管结构难?——秒了

前边我们已经学完了PN结&#xff0c;二极管&#xff0c;在分析了二极管后&#xff0c;我们对这些东西有了一定深度的了解&#xff0c;但是只给我们一个二极管去研究&#xff0c;这玩意好像真的没啥大用&#xff0c;其实我们追求的是用半导体材料去代替电子管的放大作用&#xf…

0.开篇:SSM+Spring Boot导学

1. 为什么要使用框架 Spring是一个轻量级Java开发框架&#xff0c;最早有Rod Johnson创建&#xff0c;目的是为了解决企业级应用开发的业务逻辑层和其他各层的耦合问题。 几乎当下所有企业级JavaEE开发都离不开SSM&#xff08;Spring SpringMVC MyBatis&#xff09;Spring B…

c/c++ |游戏后端开发之skynet

作者眼中的skynet 有一点要说明的是&#xff0c;云风至始也没有公开说skynet专门为游戏开发&#xff0c;换句话&#xff0c;skynet 引擎也可以用于web 开发 贴贴我的笔记 skynet 核心解决什么问题 愿景&#xff1a;游戏服务器能够充分利用多核优势&#xff0c;将不同的业务放在…

Visual Studio Code 终端为管理员权限

第一部 1、 Visual Studio Code 快捷方式启动选项加上管理员启动 第二步 管理员方式运行 powershell Windows 10的任务栏自带了搜索。或者开始菜单选搜索只需在搜索框中输入powershell。 在出来的搜索结果中右击Windows PowerShell&#xff0c;然后选择以管理员方式运行。 执…

Apache Doris 基于 Job Scheduler 实现秒级触发任务调度能力

作者&#xff5c;SelectDB 技术团队 在数据管理愈加精细化的需求背景下&#xff0c;定时调度在其中扮演着重要的角色。它通常被应用于以下场景&#xff1a; 定期数据更新&#xff0c;如周期性数据导入和 ETL 操作&#xff0c;减少人工干预&#xff0c;提高数据处理的效率和准…

Java基于微信小程序的校园外卖平台设计与实现,附源码

博主介绍&#xff1a;✌程序员徐师兄、7年大厂程序员经历。全网粉丝12w、csdn博客专家、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ &#x1f345;文末获取源码联系&#x1f345; &#x1f447;&#x1f3fb; 精彩专栏推荐订阅&#x1f447;…

03-JAVA设计模式-代理模式详解

代理模式 什么是代理模式 Java代理模式是一种常用的设计模式&#xff0c;主要用于在不修改现有类代码的情况下&#xff0c;为该类添加一些新的功能或行为。代理模式涉及到一个代理类和一个被代理类&#xff08;也称为目标对象&#xff09;。代理类负责控制对目标对象的访问&a…

Github 2024-04-09 Python开源项目日报 Top10

根据Github Trendings的统计,今日(2024-04-09统计)共有10个项目上榜。根据开发语言中项目的数量,汇总情况如下: 开发语言项目数量Python项目10Vue项目1JavaScript项目1系统设计指南 创建周期:2507 天开发语言:Python协议类型:OtherStar数量:241693 个Fork数量:42010 次…

贪心算法|860.柠檬水找零

力扣题目链接 class Solution { public:bool lemonadeChange(vector<int>& bills) {int five 0, ten 0, twenty 0;for (int bill : bills) {// 情况一if (bill 5) five;// 情况二if (bill 10) {if (five < 0) return false;ten;five--;}// 情况三if (bill …

SpringBoot快速入门笔记(6)

文章目录 Axios网络请求1、简介2、导入3、网络请求4、跨域问题5、数据渲染6、全局配置 Axios网络请求 1、简介 项目开发中&#xff0c;前端页面需要的数据往往要从服务器端获取&#xff0c;这必然涉及到和服务器的通信 Axios基于promise网络请求库&#xff0c;作用于node.js和…

Apache Incubator Answer 本地开发部署

文章目录 简介Github文档插件部署 Answer开发环境编译项目初始化项目运行项目 简介 一款适合任何团队的问答平台软件。 Apache Incubator Answer是一个开源项目&#xff0c;它是一个用于构建和部署问答系统的框架。该项目是Apache软件基金会的孵化器项目&#xff0c;提供一个…

PVE下安装配置openwrt和ikuai

开端 openwrt 和 ikuai 是比较出名的软路由系统。我最早接触软路由还是因为我的一个学长要改自己家里的网络&#xff0c;使用软路由去控制网络。我听说后便来了兴致&#xff0c;也在我家搞了一套软路由系统。现在我已经做完了&#xff0c;就想着写个文章记录一下。 软路由简介…

云数据库价格一瞥(华为云、百度智能云、腾讯云、阿里云)

最近&#xff0c;大家似乎和价格“磕”上了。本文仅考虑主流产品&#xff08; RDS MySQL、Redis &#xff09;的部分主流规格&#xff0c;对各家厂商的价格做一个对比&#xff0c;供参考。 TL;DR&#xff1a; 总体来看&#xff0c;各家云厂商价格趋于持平&#xff0c;部分主流商…

关于阿里云centos系统下宝塔面板部署django/中pip install mysqlclient失败问题的大总结/阿里云使用oss长期访问凭证

python版本3.12.0 问题1 解决方案 sudo vim /etc/profile export MYSQLCLIENT_CFLAGS"-I/usr/include/mysql" export MYSQLCLIENT_LDFLAGS"-L/usr/lib64/mysql" Esc退出编辑模式 &#xff1a;wq退出并且保存 问题二 说是找不到 mysql.h头文件 CentOS ‘…

【数据结构】考研真题攻克与重点知识点剖析 - 第 8 篇:排序

前言 本文基础知识部分来自于b站&#xff1a;分享笔记的好人儿的思维导图与王道考研课程&#xff0c;感谢大佬的开源精神&#xff0c;习题来自老师划的重点以及考研真题。此前我尝试了完全使用Python或是结合大语言模型对考研真题进行数据清洗与可视化分析&#xff0c;本人技术…

Python单元测试pytest捕获日志输出

使用pytest进行单元测试时&#xff0c;遇到了需要测试日志输出的情况&#xff0c;查看了文档 https://docs.pytest.org/en/latest/how-to/capture-stdout-stderr.html https://docs.pytest.org/en/latest/how-to/logging.html 然后试了一下&#xff0c;捕捉logger.info可以用…