RabbitMQ~架构、能力、AMQP、工作模式、高可用、死信队列了、事务机制了解

news2024/11/15 19:48:05

RabbitMQ

RabbitMQ是使用Erlang编写的一个开源的消息中间件。它实现了AMQP(高级消息队列协议),并支持其他消息传递协议:例如STOMP(简单文本定向消息协议)和MQTT(物联网协议)。

支持多种客户端如:Python、Ruby、.NET、Java、JMS、C、PHP、ActionScript、XMPP、STOMP等。
用于在分布式系统中存储转发消息,在易用性、扩展性、高可用用性等方面表现不俗。

本身支持很多的协议:AMQP,MQTT,XMPP, SMTP, STOMP,也正是如此,使的它变的非常重量级
它同时实现了一个Broker构架,这意味着消息在发送给客户端时先在中心队列排队,对路由(Routing)、负载均衡(Load balance)或者数据持久化都有很好的支持。

所以最大的特点就是:灵活的路由 : 在消息进入队列之前,通过交换器来路由消息。对于典型的路由功能, RabbitMQ 己经提供了一些内置的交换器来实现。针对更复杂的路由功能,可以将多个交换器绑定在一起, 也可以通过插件机制来实现自己的交换器。依据该特点,衍生出多种工作模式,但是因为集群模式限制吞吐量不行

架构

整体架构如下:
在这里插入图片描述

  • Producer(生产者) :生产消息的一方

  • Consumer(消费者) :消费消息的一方

消息一般由 2 部分组成:消息头(或者说是标签 Label)和 消息体。消息体也可以称为 payLoad ,消息体是不透明的,而消息头则由一系列的可选属性组成,这些属性包括 routing-key(路由键)、priority(相对于其他消息的优先权)、delivery-mode(指出该消息可能需要持久性存储)等。生产者把消息交由 RabbitMQ 后,RabbitMQ 会根据消息头把消息发送给感兴趣的 Consumer(消费者)。

  • Exchange(交换器) :在 RabbitMQ 中,消息并不是直接被投递到 Queue(消息队列) 中的,中间还必须经过 Exchange(交换器) 这一层,Exchange(交换器) 会把我们的消息分配到对应的 Queue(消息队列) 中。Exchange(交换器) 用来接收生产者发送的消息并将这些消息路由给服务器中的队列中,如果路由不到,或许会返回给 Producer(生产者) ,或许会被直接丢弃掉 。这里可以将 RabbitMQ 中的交换器看作一个简单的实体。RabbitMQ 的 Exchange(交换器) 有 4 种类型,不同的类型对应着不同的路由策略:direct(默认),fanout, topic, 和 headers,不同类型的 Exchange 转发消息的策略有所区别。核心要素就是中心化管理消息路由规则

  • Queue(消息队列): 用来保存消息直到发送给消费者。它是消息的容器,也是消息的终点。一个消息可投入一个或多个队列。消息一直在队列里面,等待消费者连接到这个队列将其取走。RabbitMQ 中消息只能存储在 队列 中,这一点和 Kafka 这种消息中间件相反。Kafka 将消息存储在 topic(主题) 这个逻辑层面,而相对应的队列逻辑只是 topic 实际存储文件中的位移标识。 RabbitMQ 的生产者生产消息并最终投递到队列中,消费者可以从队列中获取消息并消费。多个消费者可以订阅同一个队列,这时队列中的消息会被平均分摊(Round-Robin,即轮询)给多个消费者进行处理,而不是每个消费者都收到所有的消息并处理,这样避免消息被重复消费。

  • Brocker(服务节点):对于 RabbitMQ 来说,一个 RabbitMQ Broker 可以简单地看作一个 RabbitMQ 服务节点,或者 RabbitMQ 服务实例。大多数情况下也可以将一个 RabbitMQ Broker 看作一台 RabbitMQ 服务器。

  • VHost:是RabbitMQ中虚拟主机的概念,它类似于操作系统中的命名空间,用于将RabbitMQ的资源进行隔离和分组。每个VHost拥有自己的交换器、队列、绑定和权限设置,不同VHost之间的资源相互独立,互不干扰。VHost可以用于将不同的应用或服务进行隔离,以防止彼此之间的消息冲突和资源竞争

  • Channel(信道):由于 TCP 链接的创建和销毁开销较大,且并发数受系统资源限制,会造成性能瓶颈,所以 RabbitMQ 使用信道的方式来传输数据。信道(Channel)是生产者、消费者与 RabbitMQ 通信的渠道,信道是建立在 TCP 链接上的虚拟链接,且每条 TCP 链接上的信道数量没有限制。就是说 RabbitMQ 在一条 TCP 链接上建立成百上千个信道来达到多个线程处理,这个 TCP 被多个线程共享,每个信道在 RabbitMQ 都有唯一的 ID,保证了信道私有性,每个信道对应一个线程使用。

Exchange类型

RabbitMQ 中通过 Binding(绑定) 将 Exchange(交换器) 与 Queue(消息队列) 关联起来,在绑定的时候一般会指定一个 BindingKey(绑定建) ,这样 RabbitMQ 就知道如何正确将消息路由到队列了。一个绑定就是基于路由键将交换器和消息队列连接起来的路由规则,所以可以将交换器理解成一个由绑定构成的路由表。Exchange 和 Queue 的绑定可以是多对多的关系。

RabbitMQ 常用的 Exchange Type 有 fanout、direct、topic、headers 这四种(AMQP 规范里还提到两种 Exchange Type,分别为 system 与 自定义,这里不予以描述)。

  1. fanout:fanout 类型的 Exchange 路由规则非常简单,它会把所有发送到该 Exchange 的消息路由到所有与它绑定的 Queue 中,不需要做任何判断操作,所以 fanout 类型是所有的交换机类型里面速度最快的。fanout 类型常用来广播消息

  2. direct(默认):direct 类型的 Exchange 路由规则也很简单,它会把消息路由到那些 Bindingkey 与 RoutingKey 完全匹配的 Queue 中。

在这里插入图片描述

以上图为例,如果发送消息的时候设置路由键为“warning”,那么消息会路由到 Queue1 和 Queue2。如果在发送消息的时候设置路由键为"Info”或者"debug”,消息只会路由到 Queue2。如果以其他的路由键发送消息,则消息不会路由到这两个队列中。
direct 类型常用在处理有优先级的任务,根据任务的优先级把消息发送到对应的队列,这样可以指派更多的资源去处理高优先级的队列

  1. topic:前面讲到 direct 类型的交换器路由规则是完全匹配 BindingKey 和 RoutingKey ,但是这种严格的匹配方式在很多情况下不能满足实际业务的需求。topic 类型的交换器在匹配规则上进行了扩展,它与 direct 类型的交换器相似,也是将消息路由到 BindingKey 和 RoutingKey 相匹配的队列中,但这里的匹配规则有些不同,它约定:RoutingKey 为一个点号“.”分隔的字符串(被点号“.”分隔开的每一段独立的字符串称为一个单词),如 “com.rabbitmq.client”、“java.util.concurrent”、“com.hidden.client”;BindingKey 和 RoutingKey 一样也是点号“.”分隔的字符串;BindingKey 中可以存在两种特殊字符串“”和“#”,用于做模糊匹配,其中“”用于匹配一个单词,“#”用于匹配多个单词(可以是零个)。
    在这里插入图片描述
  2. headers(不推荐):headers 类型的交换器不依赖于路由键的匹配规则来路由消息,而是根据发送的消息内容中的 headers 属性进行匹配。在绑定队列和交换器时指定一组键值对,当发送消息到交换器时,RabbitMQ 会获取到该消息的 headers(也是一个键值对的形式),对比其中的键值对是否完全匹配队列和交换器绑定时指定的键值对,如果完全匹配则消息会路由到该队列,否则不会路由到该队列。headers 类型的交换器性能会很差,而且也不实用,基本上不会看到它的存在。

AMQP

RabbitMQ 中的交换器、交换器类型、队列、绑定、路由键等都是遵循的 AMQP 协议中相 应的概念。

目前 RabbitMQ 最新版本默认支持的是 AMQP 0-9-1。

AMQP 协议的三层:

  • Module Layer:协议最高层,主要定义了一些客户端调用的命令,客户端可以用这些命令实现自己的业务逻辑。
  • Session Layer:中间层,主要负责客户端命令发送给服务器,再将服务端应答返回客户端,提供可靠性同步机制和错误处理。
  • TransportLayer:最底层,主要传输二进制数据流,提供帧的处理、信道复用、错误检测和数据表示等。

AMQP 模型的三大组件:

  1. 交换器 (Exchange):消息代理服务器中用于把消息路由到队列的组件。
  2. 队列 (Queue):用来存储消息的数据结构,位于硬盘或内存中。
  3. 绑定 (Binding):一套规则,告知交换器消息应该将消息投递给哪个队列。

工作模式

RabbitMQ一共有6种工作模式(消息分发方式)分别是简!单模式、工作队列模式、发布订阅模式、路由模式、主题模式以及RPC模式。

  • 简单模式是最基本的工作模式,也是最简单的消息传递模式。在简单模式中,一个生产者将消息发送到一个队列中,一个消费者从队列中获取并处理消息。这种模式适用于单个生产者和单个消费者的简单场景,消息的处理是同步的。
  • 工作队列模式用于实现一个任务在多个消费者之间的并发处理。在工作队列模式中,一个生产者将消息发送到一个队列中,多个消费者从队列中获取并处理消息。每个消息只能被一个消费者处理。这种模式适用于多个消费者并发处理消息的情况,提高了系统的处理能力和吞吐量。
  • 发布/订阅模式用于实现一条消息被多个消费者同时接收和处理。在发布/订阅模式中,一个生产者将消息发送到交换器(Exchange)中,交换器将消息广播到所有绑定的队列,每个队列对应一个消费者。这种模式适用于消息需要被多个消费者同时接收和处理的广播场景,如事件通知等。
  • 路由模式用于实现根据消息的路由键(Routing Key)将消息路由到不同的队列中。在路由模式中,一个生产者将消息发送到交换器中,并指定消息的路由键,交换器根据路由健将消息路由到与之匹配的队列中。这种模式适用于根据不同的条件将消息发送到不同的队列中,以实现消息的筛选和分发。
  • 主题模式是一种更灵活的消息路由模式,它使用通配符匹配路由键,将消息路由到多个队列中。在主题模式中,一个生产者将消息发送到交换器中,并指定主题(Topic)作为路由键,交换器根据通配符匹配将消息路由到与之匹配的队列中。这种模式适用于消息的复杂路由需求,可以实现高高度灵活的消息筛选和分发。
  • RPC模式是一种用于实现分布式系统中远程调用的工作模式。指的是通过rabbitMQ来实现一种RPC的能力。

高可用部署

RabbitMQ有三种模式:单机模式、普通集群模式、镜像集群模式。

  • 单机模式

其中单机模式一般用于demo搭建,不适合在生产环境中使用。

  • 普通集群模式

意思就是在多台机器上启动多个RabbitMQ实例,每个机器居动一个。你创建的queue,只会放在一个RabbitMQ实例上,但是每个实例都同步queue的元数据(元数据可以认为是queue的一些配置信息,通过元数据,可以找到queue所在实例)。你消费的时候,实际上如果连接到了另外一个实例,那么那个实例会从queue所在实例上拉取数据过来。这方案主要是提高吞吐量的,就是说让集群中多个节点来服务某个queue的读写操作。
在这里插入图片描述在这种模式下,我们创建的Queue,它的元数据(配置信息)会在集群中的所有实例间进行同步,但是队列中的消息只会存在于一个RabbitMQ实例上,而不会同步到其他队列。

当我们消费消息的时候,如果消费者连接到了未保存消息的实例,那么那个实例会通过元数据定位到消息所在的实例,拉取数据过来发送给消费者进行消费。
消息的发送也是一样的,当发送者连接到了一个不保存消息的实例时,也会被转发到保存消息的实例上进行写操作。
这种集群模式下,每一个实例中的元数据是一样的,大家都是完整的数据。但是队列中的消息数据,在不同的实例上保存的是不一样的。这样通过增加实例的方式就可以提升整个个集群的消息存储量,以及性能
这种方式在高可用上有一定的帮助,不至于一个节点挂了就全都挂了。但是也还有缺点,至少这个实例上的数据是没办法被读写了。

  • 镜像集群模式

这种模式,才是所谓的RabbitMQ的高可用模式。跟普通集群模式不一样的是,在镜像集群模式下,你创建的queue,无论元数据还是queue里的消息都会存在于多个实例上,就是说,每个RabbitMQ节点都有这个queue的一个完整镜像,包含queue的全部数据的意思。然后每次你写消息到queue的时候,都会自动把消息同步到多个实例的queue上。RabbitMQ有很好的管理控制台,就是在后台新增一个策略,这个策略是镜像集群模式的策略,指定的时候是可以要求数据同步到所有节点的,也可以要求同步到指定数量的节点,再次创建queue的时候,应用这个策略,就会自动将数据同步到其他的节点上去了。
这样的好处在于,你任何一个机器宕机了,没事儿,其它机器(节点)还包含了这个queue的完整数据,别的consumer都可以到其它节点上去消费数据。
坏处在于,第一,这个性能开销也太大了吧,消息需要同步到所有机器上,导致网络带宽压力和消耗很重!
RabbitMQ每个queue的数据都是放在一个节点里的,镜像集群下,也是每个节点都放这个queue的完整数据。
在这里插入图片描述

如何保证消息可靠性

  • 生产者到 RabbitMQ:事务机制和 Confirm 机制,注意:事务机制和 Confirm 机制是互斥的,两者不能共存,会导致 RabbitMQ 报错。
  • RabbitMQ 自身:持久化、集群、普通模式、镜像模式。
  • RabbitMQ 到消费者:basicAck 机制、死信队列、消息补偿机制。

死信队列

DLX,全称为 Dead-Letter-Exchange,死信交换器,死信邮箱。当消息在一个队列中变成死信 (dead message) 之后,它能被重新发送到另一个交换器中,这个交换器就是 DLX,绑定 DLX 的队列就称之为死信队列。

导致的死信的几种原因:

  1. 消息被拒(Basic.Reject /Basic.Nack) 且 requeue = false。
  2. 消息 TTL 过期。
  3. 队列满了,无法再添加。

事务机制,保证消息发送成功

一种是通过conffirm机制,另外一种就是通过事务机制。
RabbitMQ的事务机制,允许生产者将一组操作打包成一个原子事务单元,要么全部执行成功,要么全部失败。事务提供了一种确保消息完整性的方法,但需要谨慎使用,因为它们对性能有一定的影响。
RabbitMQ是基于AMQP协议实现的,RabbitMQ中,事务是通过在通道(Channel)上启用的,与事务机制有关的方法有三个:

  • txSelect():将当前channel设置成transaction模式。
  • txCommit():提交事务。
  • txRollback():回滚事务。

我们需要先通过txSelect开启事务,然后就可以发布消息给MQ了,如果txCommit提交成功了,则消息一定到达了RabbitMQ,如果在txCommit执行之前RabbitMQ实例异常崩溃或者抛出异常,那我们就可以捕获这个异常然后执行txRollback进行回滚事务。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

4-7 使用bios 中断 读取磁盘

1 首先是逻辑。 首先来看一下 他的编译代码的逻辑。 可以看到我 生成的 实际上是 Boot.bin , 这个文件可不止一个扇区, 然后将这个文件写入到了, disk1.img 这里加载了 disk1.img , disk2.img 我不太理解。 但是可以跑通, 暂时先不管了。…

How can I change from OpenAI to ChatOpenAI in langchain and Flask?

题意:“在 LangChain 和 Flask 中,如何将 OpenAI 更改为 ChatOpenAI?” 问题背景: This is an implementation based on langchain and flask and refers to an implementation to be able to stream responses from the OpenAI …

力扣763-划分字母区间(Java详细题解)

题目链接:763. 划分字母区间 - 力扣(LeetCode) 前情提要: 因为本人最近都来刷贪心类的题目所以该题就默认用贪心方法来做。 贪心方法:局部最优推出全局最优。 如果一个题你觉得可以用局部最优推出全局最优&#xf…

云服务器系统盘存储空间不够用怎么办?解决方法:扩容或挂载数据盘

云服务器系统盘满了不够用怎么办?服务器百科:可以系统盘扩容,也可以通过挂载数据盘来增大存储空间。 1、系统盘扩容教程:使用云服务器系统盘空间不足时,可以在ECS控制台上扩容云盘的容量以增加存储空间。阿里云支持云…

MCU3.电平等一些名词

1.电平的简单定义 计算机由各种硬件组成,只认识0和1,可以通过改变电压来向计算机输入数据(0和1) 例如:最大电压为3.3V 电压范围是0~3.3V,可以定义0~1V较低的电压表示0,定义2~3.3V较高的电压表…

领域驱动设计——大型结构(Large-Scale Structure)的综合运用

在一个大的、复杂的系统中,可能需要在一个设计中综合运用几种策略。那么,大型结构如何与CONTEXT MAP共存?应该把构造块放到哪里?第一步先做什么?第二步和第三步呢?如何设计你的战略? 把大型结构与BOUNDED CONTEXT结合起来使用 战略设计的3个基本原…

SpringBoot中@Value获取值和@ConfigurationProperties获取值用法及比较

SpringBoot中Value获取值和ConfigurationProperties获取值用法及比较 更新时间:2024年08月08日 09:41:48 作者:岳轩子 在Spring Boot中,Value注解是一个非常有用的特性,它允许我们将外部的配置注入到我们的Bean中,ConfigurationProperties用于将配置文件…

理解调试和组织 CSS——WEB开发系列26

CSS(层叠样式表)不仅是为网页提供样式的关键工具,也是调试和优化网页表现的重要部分。无论是调整网页布局,还是确保样式的一致性,掌握调试和组织 CSS 的技巧都是至关重要的。 一、使用浏览器开发者工具 浏览器开发者工…

【国外比较权威的免费的卫星数据网站——Sentinel Open Access Hub】

Sentinel Open Access Hub 网址:https://scihub.copernicus.eu/dhus/#/home简介:哨兵系列卫星科研数据中心(Sentinel Open Access Hub)是欧洲航天局(ESA)提供卫星数据的官方网站。该网站提供哨兵系列卫星的…

八、2 DMA数据转运 DMA函数介绍

把数组定义在Flash中,可以节省SRAM的空间 去掉const不会影响程序运行,但会占用SRAM的空间 1、步骤 (1)RCC开启DMAD的时钟 (2)调用DMA_Init,初始化参数 (3)调用DMA_Cmd…

Java的动态代理(实际案例秒懂!)

在看动态代理解决两个案例之前,请先看链接VCR 《java代理》2分钟动画_哔哩哔哩_bilibili 一.动态代理-精致小案例 需求分析 传统方法 就是定义一个接口,然后实现类去实现规定的run方法 缺点:代码很冗余,有一些运行前和运行后…

C++ | Leetcode C++题解之第385题迷你语法分析器

题目: 题解: class Solution { public:int index 0;NestedInteger deserialize(string s) {if (s[index] [) {index;NestedInteger ni;while (s[index] ! ]) {ni.add(deserialize(s));if (s[index] ,) {index;}}index;return ni;} else {bool negati…

超实用!如何用搜索引擎提升你的工作效率

平常用的Google浏览器比较多,所以分享下Google Chrome一些能提高工作效率的配置和操作以及如何巧妙利用Google搜索技巧快速找我们想要的数据 1. 浏览器设置 1. 搜索引擎快速切换 使用效果: 2. 历史记录快速打开 效果展示: 3. 隐藏显示书…

线性约束最小方差准则(LCMV)波束形成算法及MATLAB深入仿真分析

阵列信号处理——线性约束最小方差准则(LCMV)波束形成算法及MATLAB深入仿真分析 目录 前言 一、LCMV算法 二、仿真参数设置 三、抗干扰权值计算仿真 四、不同干扰方位下抗干扰性能仿真 五、不同信噪比和干噪比下抗干扰性能仿真 总结 前言 在信号处理模块中,通…

Vue——认识day06_class与style绑定

在Vue中,可以使用v-bind指令来将CSS样式动态地绑定到HTML元素上。有两种方式可以实现CSS与style的绑定: 对象语法:可以将一个包含CSS属性和值的对象传递给v-bind,将对象的属性与HTML元素的style属性进行绑定。例如: …

使用 Docker 搭建企业级私有仓库HARBOR

目录 1 HARBOR 的获取 1.1 下载软件包地址 1.2 HARBOR 的介绍 2 部署harbor 2.1 仓库端操作 2.1.1 修改harbor配置文件 2.1.2 生成服务端的证书与秘钥 2.1.3 管理HARBOR 2.1.4 查看是否运行 2.2 客户端操作 2.2.1 证书拷贝给客户端 2.2.2 环境配置 2.2.3 批量读取本地镜像 2.2…

Transformer面试真题详解——覆盖99%的Transformer面试问题(建议收藏)

文章目录 1. 请简述一下Transformer的基本结构和原理2. Transformer为什么使用多头注意力机制3. Transformer计算attention为什么选择点乘而不是加法?两个计算复杂度和效果上有什么区别?4. 为什么在softmax之后要对attention进行scaled(为什么…

dubbo之时间轮算法分析

文章目录 前言一、参数说明二、具体实现1、HashedWheelTimer2、createWheel3、newTimeout4、start5、run6、waitForNextTick7、transferTimeoutsToBuckets8、expireTimeouts 总结 前言 时间轮(TimingWheel)是一种高效利用线程资源进行批量化调度的算法&…

ffmpeg音频编码

音视频播放的流程 根据我之前的文章 我们已经从解复用,解码得到原始数据,现在我们逆向,将frame转化packet。也就是原始数据转化为压缩后的数据文件。 介绍 PCM样本格式 PCM(Pulse Code Modulation,脉冲编码调制)⾳频数据是未经…

离散数学------关系理论

一、序偶和笛卡尔积 序偶 两个序偶如果相等,那么他们相对应的第一第二元素分别相等 笛卡尔积 笛卡尔积是集合之间的一种运算,运算的结果是个序偶,第一元素来自前面的集合,第二元素来自后面的集合。 两集合进行笛卡尔积运算后集合…