rabbitmq中的消息有id吗_RabbitMQ 架构

文章内容输出来源:拉勾教育Java高薪训练营;

RabbitMQ 简介

RabbitMQ,俗称“兔子MQ”(可见其轻巧,敏捷),是目前非常热门的一款开源消息中间件,不管是互联网行业还是传统行业都广泛使用(最早是为了解决电信行业系统之间的可靠通信而设计)。

  1. 高可靠性、易扩展、高可用、功能丰富等
  2. 支持大多数(甚至冷门)的编程语言客户端。
  3. RabbitMQ遵循AMQP协议,自身采用Erlang(一种由爱立信开发的通用面向并发编程的语言)编写。
  4. abbitMQ也支持MQTT等其他协议
  5. 强大的插件扩展能力。

插件介绍官网:

https://www. rabbitmq.com/community- plugins.html

RabbitMQ 整体架构如下:

fc13c587f432145625618b5d6a8688ab.png

交换器

生产者发送消息到 RabbitMQ 的交换器上。常用的交换器有四种:

  • fanout 。会把所有发送到该交换器的消息路由到与该交换器绑定的消息队列中。

ae70aa821d5b21ac53539164c5d2406e.png
  • Direct。会把消息路由到bingingKey 和RoutingKey 完全匹配的队列中。

3e7b77278e114f708e27cb967980f3ff.png
  • Topic。Topic 类型的交换器哎在 direct 匹配规则上进行了扩展,不是进行完全匹配,而是进行模糊匹配。匹配规则如下:BindingKey和RoutingKey一样都是由"."分隔的字符串;BindingKey中可以存在两种特殊字符“” 和 “#”,用于模糊匹配,其中""用于匹配一个单词,"#"用于匹配多个单词(可以是0个)。

26d9751b0c3744222f32b46decc232bd.png
  • Headers 。Handers 类型的交换器不是根据路由匹配规则来的,而是根据消息中的 headers 属性进行匹配的。在绑定队列和交换器时指定一组键值对,当发送的消息到交换器时,RabbitMQ会获取到该消息的headers,对比其中的键值对是否完全匹配队列和交换器绑定时指定的键值对,如果匹配,消息就会路由到该队列。headers类型的交换器性能很差,不实用。

RabbitMQ 的数据存储机制

RabbitMQ消息有持久化消息和非持久化消息。

持久化消息在到达队列时写入磁盘,同时在内存中保存一份备份,当内存不足时,消息从内存中清除。

非持久化消息一般只存在内存中,当内存不足时进行数据的刷盘处理。节省内存空间。

RabbitMQ 存储层包含两部分,队列索引和消息存储。索引维护队列的落盘消息的信息,比如存储地点、是否已经被消费者接收,是否已经被消费者ack等,每个队列都有相应的索引。

索引使用顺序的段文件来存储,后缀为 .idx ,文件名从0开始累加,每个段文件中包含固定的记录数,默认是16384 ,每个index从磁盘中读取消息的时候,都会在内中中维护一段文件。

消息存储。消息通过键值对的形式存储到文件中,一个虚拟主机上的所有队列使用同一块存储,每个接地那只有一个。存储分为:

  • 持久化存储。在broker 重启后不会丢失。
  • 临时存储。在broker 重启后会丢失。

存储方式为文件来存储,后缀为 .rdq 。经过store 处理的所有消息都会以追加的方式写入到该文件中,当文件达到指定容量时,会创建一个新的文件进行写入。

读取消息时,先根据消息的ID(msg_id)找到对应存储的文件,如果文件存在并且未被锁住,则直接打开文件,从指定位置读取消息内容。如果文件不存在或者被锁住了,则发送请求由store进行处理。

删除消息时,只是从ETS表删除指定消息的相关信息,同时更新消息对应的存储文件和相关信息。在执行消息删除操作时,并不立即对文件中的消息进行删除,也就是说消息依然在文件中,仅仅是标记为垃圾数据而已。当一个文件中都是垃圾数据时可以将这个文件删除。当检测到前后两个文件中的有效数据可以合并成一个文件,并且所有的垃圾数据的大小和所有文件(至少有3个文件存在的情况下)的数据大小的比值超过设置的阈值garbage_fraction(默认值0.5)时,才会触发垃圾回收,将这两个文件合并,执行合并的两个文件一定是逻辑上相邻的两个文件。

RabbitMQ工作模式详解

官网地址:

https://www. rabbitmq.com/getstarted .htm

工作队列

生产者发消息,启动多个消费者实例来消费消息,每个消费者仅消费部分信息,可达到负载均衡的效果。

785f7b33924fd0751728def69530a7ea.png

生产者往队列中发送消息,多有个消费者从这个队列中消费消息,队列中的消息只能被一个消费者消费。

发布订阅模式

使用 fanout 类型交换器,routingKey 忽略。每个消费者定义生成一个队列并绑定到同一个Exchange,每个消费者都可以消费到完整的消息。

消息广播给所有订阅该消息的消费者。

在RabbitMQ中,生产者不是将消息直接发送给消息队列,实际上生产者根本不知道一个消息被发送到哪个队列。生产者将消息发送给交换器。交换器非常简单,从生产者接收消息,将消息推送给消息队列。交换器必须清楚地知道要怎么处理接收到的消息。应该是追加到一个指定的队列,还是追加到多个队列,还是丢弃。规则就是交换器类型。

0e93521fa34e43018c21deb53290fdc4.png

生产者发送消息不会直接到队列中,而是发送到对应的交换器中,然后通过交换器发送到与该交换器绑定的消息队列中。

路由模式

使用 direct 类型的Exchange,发N条消费并使用不同的 routingKey ,消费者定义队列并将队列、 routingKey 、Exchange绑定。此时使用 direct 模式Exchagne必须要 routingKey 完全匹配的情况下消息才会转发到对应的队列中被消费。

direct 交换器

分布式系统中有很多应用,这些应用需要运维平台的监控,其中一个重要的信息就是服务器的日志记录。我们需要将不同日志级别的日志记录交给不同的应用处理。

如何解决?

使用direct交换器。如果要对不同的消息做不同的处理,此时不能使用 fanout 类型的交换器,因为它只会盲目的广播消息。我们需要使用 direct 类型的交换器。 direct 交换器的路由算法很简单:只要消息的 routingKey 和队列的 bindingKey 对应,消息就可以推送给该队列。

4a10b904098eb42390500c633c43baa3.png

上图中的交换器 X 是 direct 类型的交换器,绑定的两个队列中,一个队列的 bindingKey 是 orange ,另一个队列的 bindingKey 是 black 和 green 。如此,则 routingKey 是 orange 的消息发送给队列Q1, routingKey 是 black 和 green 的消息发送给Q2队列,其他消息丢弃。

主题模式

使用 topic 类型的交换器,队列绑定到交换器、 bindingKey 时使用通配符,交换器将消息路由转发到具体队列时会根据消息 routingKey 模糊匹配,比较灵活。

上个模式中,我们通过 direct 类型的交换器做到了根据日志级别的不同,将消息发送给了不同队列的。这里有一个限制,加入现在我不仅想根据日志级别划分日志消息,还想根据日志来源划分日志,怎么做?

比如,我想监听cron服务发送的 error 消息,又想监听从kern服务发送的所有消息。此时可以使用RabbitMQ的主题模式( Topic )。

要想 topic 类型的交换器, routingKey 就不能随便写了,它必须得是点分单词。单词可以随便写,生产中一般使用消息的特征。如:“stock.usd.nyse”,“nyse.vmw”,“quick.orange.rabbit”等。该点分单词字符串最长255字节。

bindingKey 也必须是这种形式。 topic 类型的交换器背后原理跟 direct 类型的类似:只要队列的 bindingKey 的值与消息的 routingKey 匹配,队列就可以收到该消息。有两个不同:

1. * (star)匹配一个单词
2. # 匹配0到多个单词

b8d2ce0d46e1b392e6b24daad449ef4a.png

上图中,我们发送描述动物的消息。消息发送的时候指定的 routingKey 包含了三个词,两个点。第一个单词表示动物的速度,第二个是颜色,第三个是物种:..。

创建三个绑定:Q1绑定到" .orange. "Q2绑定到" ..rabbit "和" lazy.# "。

  1. Q1关注orange颜色动物的消息
  2. Q2关注兔子的消息,以及所有懒的动物消息

如果不能匹配,就丢弃消息。

如果发送的消息 routingKey 是" lazy.orange.male.rabbit ",则会匹配最后一个绑定。

如果在 topic 类型的交换器中 bindingKey 使用 # ,则就是 fanout 类型交换器的行为。

如果在 topic 类型的交换器中 bindingKey 中不使用 * 和 # ,则就是 direct 类型交换器的行为。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值