【RabbitMQ高级功能详解以及常用插件实战】

文章目录

  • 队列
    • 1 、Classic经典队列
    • 2、Quorum仲裁队列
    • 3、Stream流式队列
    • 4、如何使用不同类型的队列
  • 二、死信队列

队列

classic经典队列,Quorum仲裁队列,Stream流式队列

1 、Classic经典队列

这是RabbitMQ最为经典的队列类型。在单机环境中,拥有比较高的消息可靠性。

在RabbitMQ中,经典队列是一种非常传统的队列结构。消息以FIFO先进先出的方式存入队列。消息被

Consumer从队列中取出后就会从队列中删除。如果消息需要重新投递,就需要再次入队。这种队列都依靠

各个Broker自己进行管理,在分布式场景下,管理效率是不太高的。并且这种经典队列不适合积累太多的消

息。如果队列中积累的消息太多了,会严重影响客户端生产消息以及消费消息的性能。因此,经典队列主要

用在数据量比较小,并且生产消息和消费消息的速度比较稳定的业务场景。比如内部系统之间的服务调用。

2、Quorum仲裁队列

仲裁队列,是RabbitMQ从3.8.0版本,引入的一个新的队列类型,整个3.8.X版本,也都是在围绕仲裁队列

进行完善和优化。仲裁队列相比Classic经典队列,在分布式环境下对消息的可靠性保障更高。官方文档中表

示,未来会使用Quorum仲裁队列代替传统Classic队列。

Quorum是基于Raft一致性协议实现的一种新型的分布式消息队列,他实现了持久化,多备份的FIFO队

列,主要就是针对RabbitMQ的镜像模式设计的。简单理解就是quorum队列中的消息需要有集群中多半节点

同意确认后,才会写入到队列中。这种队列类似于RocketMQ当中的DLedger集群。这种方式可以保证消息

在集群内部不会丢失。同时,Quorum是以牺牲很多高级队列特性为代价,来进一步保证消息在分布式环境

下的高可靠。

从整体功能上来说,Quorum队列是在Classic经典队列的基础上做减法,因此对于RabbitMQ的长期使用

者而言,其实是会影响使用体验的。

Quorum队列大部分功能都是在Classic队列基础上做减法,比如Nondurable queues表示是非持久化的内存队列。Exclusivity表示独占队列,即表示队列只能由声明该队列的

Connection连接来进行使用,包括队列创建、删除、收发消息等,并且独占队列会在声明该队列的

Connection断开后自动删除。

其中有个特例就是Poison Message handling(处理有毒的消息)。所谓毒消息是指消息一直不能被消费者正

常消费(可能是由于消费者失败或者消费逻辑有问题等),就会导致消息不断的重新入队,这样这些消息就成

为了毒消息。这些读消息应该有保障机制进行标记并及时删除。Quorum队列会持续跟踪消息的失败投递尝

试次数,并记录在"x-delivery-count"这样一个头部参数中。然后,就可以通过设置 Delivery limit参数来定

制一个毒消息的删除策略。当消息的重复投递次数超过了Delivery limit参数阈值时,RabbitMQ就会删除这

些毒消息。当然,如果配置了死信队列的话,就会进入对应的死信队列。

Quorum队列更适合于 队列长期存在,并且对容错、数据安全方面的要求比低延迟、不持久等高级队列更能

要求更严格的场景。例如 电商系统的订单,引入MQ后,处理速度可以慢一点,但是订单不能丢失。

也对应以下一些不适合使用的场景:

1、一些临时使用的队列:比如transient临时队列,exclusive独占队列,或者经常会修改和删除的队列。

2、对消息低延迟要求高: 一致性算法会影响消息的延迟。

3、对数据安全性要求不高:Quorum队列需要消费者手动通知或者生产者手动确认。

4、队列消息积压严重 : 如果队列中的消息很大,或者积压的消息很多,就不要使用Quorum队列。

Quorum队列当前会将所有消息始终保存在内存中,直到达到内存使用极限。

3、Stream流式队列

Stream队列是RabbitMQ自3.9.0版本开始引入的一种新的数据队列类型。这种队列类型的消息是持久化到

磁盘并且具备分布式备份的,更适合于消费者多,读消息非常频繁的场景。

Stream队列的核心是以append-only只添加的日志来记录消息,整体来说,就是消息将以append-only的

方式持久化到日志文件中,然后通过调整每个消费者的消费进度offset,来实现消息的多次分发。下方有几

个属性也都是来定义日志文件的大小以及保存时间。如果你熟悉Kafka或者RocketMQ,会对这种日志记录消

息的方式非常熟悉。这种队列提供了RabbitMQ已有的其他队列类型不太好实现的四个特点:

1、large fan-outs 大规模分发

当想要向多个订阅者发送相同的消息时,以往的队列类型必须为每个消费者绑定一个专用的队列。如果消

费者的数量很大,这就会导致性能低下。而Stream队列允许任意数量的消费者使用同一个队列的消息,从而

消除绑定多个队列的需求。

2、Replay/Time-travelling 消息回溯

RabbitMQ已有的这些队列类型,在消费者处理完消息后,消息都会从队列中删除,因此,无法重新读取

已经消费过的消息。而Stream队列允许用户在日志的任何一个连接点开始重新读取数据。

3、Throughput Performance 高吞吐性能

Strem队列的设计以性能为主要目标,对消息传递吞吐量的提升非常明显。

4、Large logs 大日志

RabbitMQ一直以来有一个让人诟病的地方,就是当队列中积累的消息过多时,性能下降会非常明显。但

是Stream队列的设计目标就是以最小的内存开销高效地存储大量的数据。使用Stream队列可以比较轻松的

在队列中积累百万级别的消息。

整体上来说,RabbitMQ的Stream队列,其实有很多地方借鉴了其他MQ产品的优点,在保证消息可靠性

的基础上,着力提高队列的消息吞吐量以及消息转发性能。因此,Stream也是在视图解决一个RabbitMQ一

直以来,让人诟病的缺点,就是当队列中积累的消息过多时,性能下降会非常明显的问题。RabbitMQ以往

更专注于企业级的内部使用,但是从这些队列功能可以看到,Rabbitmq也在向更复杂的互联网环境靠拢,

未来对于RabbitMQ的了解,也需要随着版本推进,不断更新。

4、如何使用不同类型的队列

这几种不同类型的队列,虽然实现方式各有不同,但是本质上都是一种存储消息的数据结构。在之前章

节,已经对Classic队列的各种编程模型进行了详细分析。而Quorum队列和Stream队列的使用方式也是大同

小异的。

1、Quorum队列

Quorum队列与Classic队列的使用方式是差不多的。最主要的差别就是在声明队列时有点不同。

如果要声明一个Quorum队列,则只需要在后面的arguments中传入一个参数,x-queue-type,参数值设定为quorum。

Quorum队列的消息是必须持久化的,所以durable参数必须设定为true,如果声明为false,就会报错。

同样,exclusive参数必须设置为false。这些声明,在Producer和Consumer中是要保持一致的。

2、Stream队列

Stream队列相比于Classic队列,在使用上就要稍微复杂一点。

如果要声明一个Stream队列,则 x-queue-type参数要设置为 stream 。

最后,在企业中,目前用的最多的还是Classic经典队列。而从RabbitMQ的官网就能看出,RabbitMQ目前

主推的是Quorum队列,甚至有传言未来会用Quorum队列全面替代Classic经典队列。至于Stream队列,虽

然已经经历了几个版本的完善修复,但是目前还是不太稳定,企业用得还比较少。

二、死信队列

死信队列是RabbitMQ中非常重要的一个特性。简单理解,他是RabbitMQ对于未能正常消费的消息进行的

一种补救机制。死信队列也是一个普通的队列,同样可以在队列上声明消费者,继续对消息进行消费处理。

1、何时会产生死信

有以下三种情况,RabbitMQ会将一个正常消息转成死信

消息被消费者确认拒绝。消费者把requeue参数设置为true(false),并且在消费后,向RabbitMQ返回

拒绝。channel.basicReject或者channel.basicNack。

消息达到预设的TTL时限还一直没有被消费。

消息由于队列已经达到最长长度限制而被丢掉

2、死信队列的配置方式

RabbitMQ中有两种方式可以声明死信队列,一种是针对某个单独队列指定对应的死信队列。另一种就是以

策略的方式进行批量死信队列的配置。

针对多个队列,可以使用策略方式,配置统一的死信队列。

在对队列进行配置时,只有Classic经典队列和Quorum仲裁队列才能配置死信队列,

而目前Stream流式队列,并不支持配置死信队列。

3、关于参数x-dead-letter-routing-key

死信在转移到死信队列时,他的Routing key 也会保存下来。但是如果配置了x-dead-letter-routing-key这

个参数的话,routingkey就会被替换为配置的这个值。

另外,死信在转移到死信队列的过程中,是没有经过消息发送者确认的,所以并不能保证消息的安全性。

4、如何确定一个消息是不是死信

消息被作为死信转移到死信队列后,会在Header当中增加一些消息。在官网的详细介绍中,可以看到很多

内容,比如时间、原因(rejected,expired,maxlen)、队列等。然后header中还会加上第一次成为死信的三个

属性,并且这三个属性在以后的传递过程中都不会更改。

x-first-death-reason

x-first-death-queue

x-first-death-exchange

5、基于死信队列实现延迟队列

其实从前面的配置过程能够看到,所谓死信交换机或者死信队列,不过是在交换机或者队列之间建立一种

死信对应关系,而死信队列可以像正常队列一样被消费。他与普通队列一样具有FIFO的特性。对死信队列的

消费逻辑通常是对这些失效消息进行一些业务上的补偿。

RabbitMQ中,是不存在延迟队列的功能的,而通常如果要用到延迟队列,就会采用TTL+死信队列的方

式来处理。

相关推荐
.生产的驴6 小时前
SpringBoot 消息队列RabbitMQ 交换机模式 Fanout广播 Direct定向 Topic话题
spring boot·rabbitmq·java-rabbitmq
王彬泽6 小时前
【RabbitMQ】消息分发、事务
rabbitmq·事务·消息分发
杰信步迈入C++之路18 小时前
【RabbitMQ】RabbitMQ 概述
分布式·rabbitmq
BLUcoding19 小时前
RabbitMQ08_保证消息可靠性
java·rabbitmq
月夜星辉雪1 天前
【RabbitMQ 项目】服务端:数据管理模块之消息管理
分布式·rabbitmq
不能再留遗憾了1 天前
RabbitMQ 高级特性——发送方确认
分布式·rabbitmq·ruby
益达_z1 天前
中间件知识点-消息中间件(Rabbitmq)一
分布式·中间件·rabbitmq
.生产的驴1 天前
SpringBoot 消息队列RabbitMQ 消息确认机制确保消息发送成功和失败 生产者确认
java·javascript·spring boot·后端·rabbitmq·负载均衡·java-rabbitmq
.生产的驴1 天前
SpringBoot 消息队列RabbitMQ在代码中声明 交换机 与 队列使用注解创建
java·spring boot·分布式·servlet·kafka·rabbitmq·java-rabbitmq
spiker_2 天前
RabbitMQ 常见使用模式详解
分布式·rabbitmq